python3 test.py  or python test.py  (could be using Python 2)
     
print("Running a Python code.")
chmod +x test.py
     ./test.py
     
#!/usr/bin/env python3
print("Executing a Python script.\n\"second line\"")
env   show environment variables env argument   running argument
     #! ...   is a 
     shebang
     int, double, boolean, ... id(var):   identification 
     number of content 
#!/usr/bin/env python3
# id: returns object identification
print("***********")
print("id checking")
print("***********")
x0 = 0                # an integer object is created
x1 = 1                # idem
print(id(x0), x0)
print(id(x1), x1, id(x1)-id(x0), "(difference in bits)\n")
print("*************")
print("type checking")
print("*************")
print("x0, type ::   ", x0, type(x0))
x0 = 'a'              # changing type from integer to string
print("x0, type ::   ", x0, type(x0))
print()   
print("****************")
print("strings as lists")
print("****************")
x0 = "I am a string"  # strings are ordered lists
x1 = " |  "  + x0[2] + x0[3]
print(x0, x1)
#!/usr/bin/env python3
from math import sqrt
print("Finding Triples  a^2 + b^2 == c^2") # ouput - not formatted
n = input("Maximum Number? ")              # input prompt
n = int(n)+1                               # casting to int
for a in range(1,n):                       # loop
  for b in range(a,n):
    ab_square = a**2 + b**2
    c = int(sqrt(ab_square))
    if (ab_square==c**2):                  # a^2 + b^2 == c^2
      print(f'{a:3d} {b:3d} | {c:3d}')     # formatted output
strings, lists, tuples   are ordered
     []   list comprehensions for compact notationrange(4) → '0,1,2,3'    on the fly;
     one by one ('lazy') [0,1,2,3]   is stored ('greedy') ()   tuples are constant collections :=   on-the-fly declaration of a variable 
(walrus assignment) 
#!/usr/bin/env python3
text = "elements of string"
print()
print(text, "  |  ", text[9]+text[10])
print()
print("*********************")
print("iterating over values")
print("*********************")
ABC = ["A", "B", "C"]              # a list
print(ABC)
for strList in ABC:                # iterating over values
  print(strList + "_" + strList)
print()
print("**********************")
print("iterating over indices")
print("**********************")
for iList in range(n:=len(ABC)):   # walrus assignment (of n)
  ABC[iList] = 'new_' + ABC[iList]
print(ABC)
print("length of ABC : ", n)
print()
print("**********************************")
print("iterating over (index,value) pairs")
print("**********************************")
for index, value in enumerate(ABC):  
    print("(", index, "|", value, ")")
print()
print("*************************")
print("using list comprehensions")
print("*************************")
[print(strList) for strList in ABC]
print()
intList = [i for i in range(10)]
print(intList)
oddList = [value*value for value in intList if value%2==1]
print(oddList)
print()
print("********************")
print("tupeles come with ()")
print("********************")
# tuples are constant collections, viz unchangeable.
fruitTuple = ("apple", "banana", "cherry")
print(fruitTuple)
# would be an erorr
# fruitTuple[0] = "changing something constant"
[]:   list are  ordered, allowing duplicates
     {}:   sets are not ordered, no duplicates {}:   dictionaries are associative sets,
     containing   (key:value)   pairs  python3 -V:   version check
     
#!/usr/bin/env python3
# second apple not stored (automatic duplicate elimination)
fruitSet = {"apple", "banana", "cherry", "apple"}
print("*********************************")
print("no ordering guranteed for sets {}")
print("*********************************")
print(fruitSet)
for fruit in fruitSet:
  if 'y' in fruit:
    fruit += " (which I like)"
  print(fruit)
print(fruitSet)
print()
print("**********************************")
print("dictionaries are associative lists")
print("**********************************")
anticCarDict = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964,
  "colors": ["red", "white", "blue"]
               }
for key in anticCarDict:
  print(f'{key:7s} ::', anticCarDict[key])
| append() | add element at the end | 
| clear() | remove all elements | 
| copy() | returns a copy | 
| count() | returns the number of elements with specified value | 
| extend() | add elements to the end | 
| index() | search for given value, returning the index of the first occurance | 
| insert() | adding element at specified position | 
| pop() | removes element at given inde | 
| remove() | removing item with specified value | 
| reverse() | reverses the order | 
| sort() | sorting | 
id()   not changed when using list operations
     
#!/usr/bin/env python3
# [-1] : last entry
myList = [i for i in range(10,17)]
print(myList)
print(len(myList), " | ", myList[-1])
myList.append("not any more a list of interges")
print(myList)
myList.insert(1, "first")
print(myList)
print()
aList = [i for i in range(5)]
bList = [i for i in range(5,8)]
# myList = aList would make them the idential object
myList = aList.copy()            # copy entire list
print("aList  :: ", aList)
print("bList  :: ", bList)
print("myList :: ", myList)
print()
myList.extend(bList)             # extend list
print("aList  :: ", aList)
print("bList  :: ", bList)
print("myList :: ", myList)
myList.sort(reverse = True)      # sorting
print("myList :: ", myList)
print()
return   defines return type
     
#!/usr/bin/env python3
# pass can be used also in for-loops
def nothingToDo():
  pass
# default argument, call by value
def flower(name='Iris'):
  print("my favorite flower is the ", name)
  name = "Orchid"
# list of arguments of arbitrary length
def allArgs(*args):
  for i in range(n:=len(args)):
    print(i, args[i])
  return n
# when using keys, the oder of calling does not matter
def keyFlowers(f3, f2, f1):
  print(f1, f2, f3)
print("*************")
print("call by value")
print("*************")
nothingToDo()
flower()
flower()
flower("Rose")
print()
myFlower = "Lily"
flower(myFlower)
print(myFlower)
print()
print("****************************")
print("arbirary number of arguments")
print("****************************")
print("argsLength: ", allArgs("Daffodil", "Dahlia", "Daisy"))
print()
print("*******************")
print("arguments with keys")
print("*******************")
# order does not matter with keys
keyFlowers(f2="Lavender", f1="Aster", f3="Poppy")
id()   unique object identifier
     copy.deepcopy()  new object copy.copy()  'shallow copy' 
#!/usr/bin/env python3
import copy             # deep and schallow copy of objects
def myFunc(inList):
 inList.append(3)
 inList.extend([7,1])
 print("id/list in myFunc     :", id(inList), inList)
 inList.remove(7)
 print("id/list in myFunc     :", id(inList), inList)
 return
def newFunc(inList):
 inList.append(3)
 inList.extend([7,1])
 print("id/list in newFunc    :", id(inList), inList)
 inList = [3, 4, 6]                   # a new id is asigned
 print("id/list in newFunc    :", id(inList), inList)
 return
def valueFunc(inList):                # simulates call by value
 localList = copy.deepcopy(inList)    # deep == recursively
 localList.extend([77,11])
 print("id/list in valueFunc  :", id(localList), localList)
 return
print("******************************")
print("id not changed within function")
print("******************************")
myList = [1, 2]
print("id/list before calling:", id(myList), myList)
myFunc(myList)
print("id/list after calling :", id(myList), myList)
print("**************************")
print("id changed within function")
print("**************************")
myList = [1]                        # a new id is asigned
print("id/list before calling:", id(myList), myList)
newFunc(myList)
print("id/list after  calling:", id(myList), myList)
print("***********************")
print("simulated call by value")
print("***********************")
myList = [11]                        # a new id is asigned
print("id/list before calling:", id(myList), myList)
valueFunc(myList)
print("id/list after  calling:", id(myList), myList)
#!/usr/bin/env python3
# list argument with empty default
# the default is however updated at every call
def spammer(bag = []):
    bag.append("spam")
    return bag
# default is None, viz list does not exists
# None is an immutable object, the empty list [] not
def noProblem(bag = None):
    if bag is None:         # check if list exists
      bag = []
    bag.append("no spam")
    return bag
print("****************")
print("using \"bag = []\"")
print("****************")
print(spammer())
print(spammer())
print(spammer())
myBag = spammer()
myBag.clear()
print(myBag)
myBag = ["no"]
print(myBag)
spammer(myBag)
print(myBag)
spammer(myBag)
print(myBag)
print()
print("******************")
print("using \"bag = None\"")
print("******************")
print(noProblem())
print(noProblem())
print(noProblem())
"""...."""   
     for multiline docstrings
     
#!/usr/bin/env python3
globalInt = 111
# the first string in a function body is the docstring
def hello():
    "function hello(): "    # the docstring
    globalInt = 22          # a local variable
    global helloInt         # becomes global
    helloInt = 33 // 2      # integer dividion (floor)    
    return hello.__doc__
print()
print("*************")
print("scope testing")
print("*************")
a = 0
for i in range(4):
  b = i
  a += i
  print("   in loop: ", a, b)
print()
print("after loop: ", a, b)       
print()
print(" globalInt: ", globalInt )  
# helloInt only created if hello called at least once
# print("  helloInt: ",  helloInt )   
print()
print("*********")
print("docstring")
print("*********")
print(hello.__doc__ + "The docstring of the function hello ")
print(hello())
x, y, z = 1, 2, 3:   process multiple objects 
      at once
#!/usr/bin/env python3
def sum_recursion(n, k=0, result=0):
  "\sum_{k=0}^n k"
  if (k <= n):
    result = k + sum_recursion(n, k+1, result)
#   print(n, k, result)             # for testing
  return result
def fibonacci(n, k=1, kk=0):
  "sum of previous two numbers"
  print(n, k, kk)                   # for testing
  if (n > 0):
    n, k, kk = fibonacci(n-1, k+kk, k) 
  return n, k, kk                   # return 3 variables
   
print("*********")
print("recursion")
print("*********")
N = 4
print(f"evaluate \"\sum_{{k=0}}^{N:d} k\" via recursion:", sum_recursion(N))
print()
print("*******************")
print("compact asignements")
print("*******************")
_, resFib, _ = fibonacci(nFib:=8)      # with placehoders '_' (and Walrus)
print(f'\nthe {nFib:d}-the Fibonacci number is: ', resFib)