1. Python variables
1.1. Python variable naming rules
1.1.1. upper/lower case letters, digits and underscore (_)
1.1.2. must begin with letter or underscore (_)
1.1.3. Python is case sensitive
1.1.4. cannot conflict with Python reserved words
1.1.4.1. Python reserved keywords
1.1.5. letters from non Latin alphabets also allowed
1.1.6. same naming rules apply to functions
1.2. Python variable declaration and assignment
1.2.1. var = val
1.2.2. you can also make multiple assignments in single line
1.2.2.1. example
1.2.2.1.1. a, b, c = 1, 3, 7
1.2.3. you can reverse variable assignments in single line
1.2.3.1. example
1.2.3.1.1. var1, var2 = var2, var1
1.2.4. you can also assign two or more variables to a single value in one line
1.2.4.1. example
1.2.4.1.1. var1 = var2 = 1
1.3. Python assignments and shortcut operators
1.3.1. Examples: += and -=
1.4. Python is dynamically typed
1.4.1. no need to declare type
1.4.2. re-assignment to different types allowed
2. Python data types
2.1. Python literal values
2.1.1. Python octal numbers
2.1.1.1. 0o prefix
2.1.2. Python hexadecimal numbers
2.1.2.1. 0x prefix
2.1.3. Python floating point numbers
2.1.3.1. Python number scientific notation
2.1.3.1.1. For very big or small numbers
2.1.3.1.2. exponent + 'E' + base
2.1.4. Python Booleans
2.2. Python strings
2.2.1. Python string escape characters
2.2.1.1. starts with \
2.2.1.1.1. example
2.2.2. Python multiline strings
2.2.2.1. """line 1 line 2"""
2.3. Python integers
3. Python PEP 8 style guide
3.1. Recommended standards for Python code style
4. Python type cast functions
4.1. Python int() function
4.2. Python float() function
4.3. Python str() function
5. Python string replication
5.1. string * 5
6. Python loops
6.1. Python while loop
6.1.1. while condition_expression: <instruction(s)>
6.1.2. if condition is false on first evaluation, loop body is not executed even once
6.1.3. loop body should include instruction(s) that eventually change while loop's condition expression to False
6.1.4. If loop body never alters condition expression from True to False, you get an endless loop
6.1.4.1. Ctrl + C usually breaks out of endless loop
6.2. instructions in loop are called loop's body
6.3. Python for loop
6.3.1. for <control variable> in <collection>: <instruction(s)>
6.3.2. number of elements in collection determines loop repetitions
6.3.3. control variable is fed next collection element on each loop
6.4. Python break and continue
6.4.1. break halts loop and exits it
6.4.2. continue halts loop body and jumps to next iteration
6.5. else clause supported for both while and for
6.5.1. always runs exactly once even when main loop body does not run at all
7. Python bitwise operators
7.1. &
7.1.1. bitwise conjunction
7.1.2. requires exactly two 1s to return 1, else 0
7.2. |
7.2.1. bitwise disjunction
7.2.2. requires at least one 1 to return 1, else 0
7.3. ~
7.3.1. bitwise negation
7.3.2. turns 1 to 0 and 0 to 1
7.4. ^
7.4.1. bitwise exclusive or (xor)
7.4.2. requires exactly one 1 to return 1, else 0
7.5. & | ^ have higher precedence than assignment operators but lower than comparison operators
7.6. Python shift operators
7.6.1. <<
7.6.1.1. left shift
7.6.1.1.1. example
7.6.2. >>
7.6.2.1. right shift
7.6.2.1.1. example
7.6.3. higher precedence than comparison operators, lower than binary arithmetic operators
7.7. arguments must be integers, floats are disallowed
7.8. unlike logical operators, bitwise operators act on individual bits of arguments
7.9. assignments, long and abbreviated
7.9.1. x = x & y
7.9.1.1. x &= y
7.9.2. x = x | y
7.9.2.1. x |= y
7.9.3. x = x ^ y
7.9.3.1. x ^= y
7.10. lowest bit is named bit number 0, second bit is bit #1, etc
7.11. bitmasks to check, reset and set bits
7.11.1. check bit (is set to 1)
7.11.1.1. if flagRegister & theMask: # my bit is set else: # my bit is reset
7.11.2. reset bit (to zero)
7.11.2.1. flagRegister = flagRegister & ~theMask
7.11.3. set bit (to 1)
7.11.3.1. flagRegister = flagRegister | theMask
7.12. Binary manipulation
8. Python methods
8.1. like function but dependent on class (object)
8.2. invocation differs to function
8.2.1. object.method()
8.3. can alter internal state of object
9. Python None value
9.1. None is a reserved keyword
9.2. you can assign to a variable or return it from an invoked function
9.3. assigning a variable to a function that doesn't include a return will assign None to that variable
10. Python backslash \ to break long lines of code
10.1. example
10.1.1. print("This is a really long line \ but we can split it over multiple lines to improve readability")
11. Python sequences
11.1. collections that have a fixed ordering to their elements
11.2. can be iterated over by a for loop
12. Multiple versions of Python
12.1. Python language was created by Guido van Rossum and first released in 1991
12.1.1. Guido is President of the Python Software Foundation (PSF)
12.1.1.1. PSF official website is python.org
12.2. Python 2 and Python 3 are two active versions that are not compatible with one another
12.2.1. Python 3 first released in 2008 is a major revision of the language
12.2.1.1. there are multiple dot releases for Python 3, which are fully backward compatible within the Python 3 family of versions
12.2.2. Python 2 development cycle ended quite some time ago, but continued to receive bug fixes, security enhancements, etc for many years
12.2.2.1. 1st Jan 2020 was Python 2 official sunset date, set by the PSF
12.2.2.1.1. Post sunset, Python 2 is officially no longer supported - no more bug fixes or security enhancements - users are urged to complete transition to Python 3
12.3. In addition to Python 2 and Python 3, there is more than one version of each
12.3.1. Pythons developed and maintained by people working under umbrella of PSF are known as canonical or reference versions - this is because Guido is President of PSF
12.3.1.1. these official versions of Python are also known as CPython
12.3.1.1.1. All versions of CPython are developed using the C language
12.3.1.1.2. Virtually all platforms have built in support for compiling and running C programs, which makes CPython highly portable across platforms
12.3.2. Cython is a Python superset that is intended to solve one of CPython's weaknesses, which is relatively slow performance (because CPython is an interpreted language)
12.3.2.1. Cython automatically translates Python code into C and in doing so makes the code significantly faster to execute
12.3.3. Jython is a version of Python developed in Java rather than C
12.3.3.1. useful for large & complex systems developed entirely with Java that need Python flexibility added
12.3.3.2. Java and C have little in common, which can make integrating CPython into Java environments difficult
12.3.3.3. Jython conforms to Python 2 standards, but does not yet support Python 3
12.3.4. PyPy is a version of Python developed in RPython
12.3.4.1. RPython stands for Restricted Python, which is a subset of CPython
12.3.4.2. Like Cython, PyPy translates Python code into C before execution, thereby making for faster code execution
12.3.4.3. PyPy is mostly used by developers that are developing the Python language itself
12.3.4.3.1. not really a choice for a regular developer like me!
12.3.4.4. PyPy supports both Python 2 and 3
13. Python functions
13.1. Python function positional arguments
13.2. Python function keyword arguments
13.2.1. if you mix keyword and positional arguments when invoking a function, all positional arguments must precede keyword, otherwise an exception will raise
13.3. Python function invocation
13.4. Python print() function
13.4.1. takes multi type arguments
13.4.2. converts all output to string type
13.5. Python built-in functions
13.6. Python input() function
13.6.1. take user input
13.6.2. optional string argument for prompt
13.6.3. must assign to variable
13.6.4. type returned is always string
13.6.4.1. but you can cast by enclosing input() in a cast function such as int()
13.7. Python range() function
13.7.1. often used with for loops
13.7.2. takes 3 args, all integers: start, stop, step
13.7.2.1. only stop is mandatory
13.7.2.1.1. last value produced is stop -1
13.7.2.2. start defaults to 0
13.7.2.3. step defaults to 1
13.7.3. example
13.7.3.1. range(10)
13.7.3.1.1. produces integers 0 to 9
13.7.3.2. range(2,8)
13.7.3.2.1. produces: 2 to 7
13.7.3.3. range(3,9,2)
13.7.3.3.1. produces: 3,5,7
13.8. Python len() function
13.8.1. often used with lists
13.8.2. takes object as argument and returns number of elements in that object
13.9. Python user-defined functions
13.9.1. syntax
13.9.1.1. def name_of_function(<optional params>): <function body>
13.9.2. functions are invoked
13.9.2.1. definition must precede invocation
13.9.2.2. after function body is executed, interpreter returns to line after invocation
13.9.3. function names must be unique and must not clash with variable names
13.9.4. if you invoke a function and pass any argument that is not matched to a parameter in the function definition, this will generate an exception
13.9.5. parameters exist inside functions, arguments exist outside functions
13.9.5.1. parameter values are set at moment of function invocation
13.9.5.2. parameters can only be declared between the parentheses ( ) of function definition
13.9.5.3. arguments can be passed two ways
13.9.5.3.1. positional arguments
13.9.5.3.2. keyword argument passing
13.9.5.3.3. you can mix styles but positional args must precede keyword args
13.9.5.3.4. beware passing arg as both positional and keyword, as it throws exception
13.9.5.4. parameters can be defined with default values, which kick in if the associated argument is omitted during invocation
13.9.5.4.1. def myFunction(firstName, lastName = "Smith"): print("Hello", firstName, lastName)
13.9.5.4.2. beware that you must place all pre-defined parameters at end, as you will get an exception if you mix them with mandatory parameters
13.9.5.5. parameters can be mapped to any valid Python type, including lists
13.9.6. parameter names can be same as variable names that are declared outside function
13.9.6.1. invokes shadowing
13.9.6.1.1. parameter takes temporary control of variable, then previous assignment returns
13.9.7. functions can produce effects and produce results
13.9.7.1. return
13.9.7.1.1. keyword
13.9.7.1.2. causes immediate termination of function body
13.9.7.1.3. without expression
13.9.7.1.4. with expression
13.9.7.1.5. functions can return any valid Python data type
13.10. Python tuple() function
13.10.1. convert an iterable type like a list or string to a tuple
13.11. Python list() function
13.11.1. convert an iterable type like a tuple or string to a list
13.12. Python dict() function
13.12.1. covert an iterable type in the right "key-value" structure to a dictionary
13.12.1.1. example of "right" structure (a tuple of tuples in this case)
13.12.1.1.1. colors = (("green", "#008000"), ("blue", "#0000FF")) colDict = {} for t in colors: colDict.update(dict([t])) print(colDict)
13.12.2. dict() supports 3 ways to create dictionary objects via its parameters: 1) keyword arguments (known as kwargs), 2) mapping, 3) iterable
13.12.2.1. **kwargs
13.12.2.1.1. print(dict(m=8, n=9))
13.12.2.1.2. kwargs can combine with mapping or iterable
13.12.2.1.3. ** means an arbitrary number of kwargs
13.12.2.2. mapping
13.12.2.2.1. print(dict({"m":8, "n":9}))
13.12.2.3. iterable
13.12.2.3.1. print(dict([("m",9),("n",10)]))
13.12.2.4. all arguments optional
13.12.2.4.1. dict()
14. Python operators
14.1. Python exponentiation
14.1.1. if either base or exponent is float vs int, float trumps and result is given in float
14.1.1.1. same applies to multiplication
14.1.2. **
14.2. Python division
14.2.1. /
14.2.2. result is always float even if dividend and divisor are int and result is whole number
14.3. Python floor division
14.3.1. //
14.3.2. aka integer division
14.3.3. Integer divisional operator (//) with one float will produce float result but fractional part rounded down to zero
14.4. Python modulo division
14.4.1. %
14.5. Binary vs Unary operators
14.5.1. Binary operator requires two arguments, one to left, one to right
14.5.1.1. Example: 3+5
14.5.2. Unary operator requires one argument to right
14.5.2.1. Example: -3
14.6. Python operator precedence
14.6.1. Python operator binding
14.6.1.1. When precedence order of operators is same, left binding generally takes precedence
14.6.1.1.1. Example: 6 % 3 % 2 is same as (6 % 3) % 2
14.6.1.1.2. Exception is exponention operator (**)
14.7. Python comparison operators
14.7.1. equality
14.7.1.1. ==
14.7.1.2. can assess int as equal to float
14.7.1.2.1. e.g. 2 == 2.0 returns True
14.7.1.3. can assess int as equal to True/False
14.7.1.3.1. e.g. 1 == True returns True
14.7.1.3.2. e.g. 0 == True returns False
14.7.1.3.3. e.g. 0 == False returns True
14.7.1.3.4. True is equal to 1, False is equal to 0
14.7.2. inequality
14.7.2.1. !=
14.7.3. less/more than
14.7.3.1. >
14.7.3.2. >=
14.7.3.3. <
14.7.3.4. <=
14.7.4. Precedence is below + and i binary operators
14.7.4.1. less/more trumps equality/inequality
15. Python comments
15.1. #
16. Python string concatenation
16.1. string + string
17. Python conditional statements
17.1. indentation important
17.1.1. must be consistent
17.1.2. cannot mix tabs and spaces
17.2. Python if statement
17.2.1. if <Boolean expression>: <instruction(s)> elif <Boolean expression>: <instruction(s)> else: <instruction(s)>
17.2.2. when branch is single instruction, Python permits it to be on same line
17.2.2.1. example
17.2.2.1.1. if a > b: x = a else: x = b
17.3. if-elif-else is known as cascade
17.3.1. else branch must always be last in cascade
17.3.2. else is optional in cascade
18. Python logical operators
18.1. binary operators
18.1.1. and
18.1.1.1. logical conjunction
18.1.2. or
18.1.2.1. lower priority than and
18.1.2.2. logical disjunction
18.1.3. lower priority than comparison operators
18.2. unary operator
18.2.1. not
18.2.1.1. very high priority
18.2.1.1.1. equivalent to unary + and -
18.2.1.2. logical negation
18.3. De Morgan's laws
18.3.1. not (p and q) == (not p) or (not q) not (p or q) == (not p) and (not q)
18.4. any non 0 bit in whole evaluates to True
18.4.1. examples
18.4.1.1. print(bool(2 + 3))
18.4.1.1.1. returns True
18.4.1.2. print(bool(2 - 2))
18.4.1.2.1. returns False
18.4.1.3. print(not bool(2))
18.4.1.3.1. returns False
19. Python Collections
19.1. Python Lists
19.1.1. defined by elements inside square brackets [ ]
19.1.2. mutable (i.e. changeable)
19.1.3. assignment example
19.1.3.1. numbers = [1, 4, 8, 10, 19]
19.1.3.2. myList = []
19.1.3.2.1. creates an empty list
19.1.4. accessed by index
19.1.4.1. zero-based
19.1.4.2. example
19.1.4.2.1. print(numbers[0])
19.1.4.2.2. print(numbers[4])
19.1.4.3. negative indexes allowed
19.1.4.3.1. -1 means last in list, -2 second to last, etc
19.1.5. duplicate values allowed
19.1.6. remove elements with del instruction
19.1.6.1. example
19.1.6.1.1. del numbers[1]
19.1.6.2. del reduces length of list (i.e. len() function will return previous value minus 1)
19.1.6.3. del can also remove slices from a list
19.1.6.3.1. example
19.1.6.4. when using del with a variable pointed to a list but no reference to an element or slice, only pointer is deleted, not the underlying list
19.1.6.4.1. example
19.1.7. Python list object methods
19.1.7.1. list.append()
19.1.7.1.1. takes 1 arg
19.1.7.1.2. adds arg to end of list
19.1.7.1.3. increases length of list by 1
19.1.7.2. list.insert()
19.1.7.2.1. takes 2 args
19.1.7.2.2. shifts all list elements to right of insert index by 1
19.1.7.2.3. increases length of list by 1
19.1.7.3. list.sort()
19.1.7.3.1. takes 0 - 2 args (i.e. both args optional)
19.1.7.4. list.reverse()
19.1.7.4.1. no args
19.1.7.4.2. reverses element order in list
19.1.7.5. list.count()
19.1.7.5.1. counts number of occurrences of arg value in list
19.1.8. for loop can access all list elements without needing to specify length or use indexes
19.1.8.1. syntax: for i in aList: print(i)
19.1.8.1.1. prints element value without needing to access index
19.1.9. Lists can be nested (e.g. lists within lists within lists, etc.)
19.1.10. List elements can be of mixed types
19.1.11. Lists can be added together using the binary + operator
19.1.11.1. list1 = [1,2] list2 = [3,4] print(list1 + list2)
19.1.11.1.1. [1,2,3,4]
19.1.12. Lists can be multiplied using the * operator and an integer
19.1.12.1. list1 = [1,2] print(list1 * 3)
19.1.12.1.1. [1,2,1,2,1,2]
19.2. Complex data types are stored differently to simple scalar types
19.2.1. for ordinary variable assigned to scalar value think of it as the name of the content
19.2.2. for variables assigned to complex types like lists, think of it as a memory location where the data is stored
19.2.2.1. important implication by example
19.2.2.1.1. list1 = [1] list2 = list1 list1[0] = 2 print(list2)
19.2.2.2. Python slice
19.2.2.2.1. use this to make copy of types like list
19.2.2.2.2. syntax is [start:end]
19.2.2.2.3. you can also specify increment, which if omitted, defaults to 1
19.3. Python membership operators
19.3.1. in
19.3.2. not in
19.3.3. return True or False when element found/not found in sequence
19.3.4. example
19.3.4.1. list1 = ["Hello","World"] print("Hello" in list1) print("Hello" not in list1)
19.3.4.1.1. returns: True False
19.4. Python list comprehension
19.4.1. Provides a concise way to create lists
19.4.2. syntax
19.4.2.1. [expression for element in list if conditional]
19.4.2.1.1. equivalent to
19.4.2.1.2. if conditional is optional
19.4.2.1.3. expression resolves to something that is added to list via the for loop
19.4.3. examples
19.4.3.1. x = "hello world" y = [x for i in range(4)] print(y)
19.4.3.1.1. returns
19.4.3.1.2. x is data used to fill list
19.4.3.1.3. clause specifying how many times to repeat x in list is: for i in range(4)
19.4.3.2. wordList = ["hello","world","how","are","you"] myWords = [w for w in wordList if w[0] == "h"] #all words beginning with 'h' print(myWords)
19.4.3.2.1. returns
19.4.3.2.2. w represents the iterating element in the list (wordList) and the data being picked to fill the new list (myWords)
19.4.3.2.3. if statement enables a conditional filter to determine which instances of w get added to new list
19.4.4. 2D arrays
19.4.4.1. aka matrix
19.4.4.2. think "table"
19.4.4.3. example
19.4.4.3.1. e = 0 myArray = [[e for i in range(3)] for i in range(3)] print(myArray)
19.5. Python sequence unpacking
19.5.1. syntactic sugar for exploding lists and tuples into multiple variable assignments in one line of code
19.5.1.1. list example
19.5.1.1.1. myList = [1, 2, 3] a, b, c = myList print(a) print(b) print(c)
19.5.1.2. tuple example
19.5.1.2.1. myTuple = (4, 5, 6) a, b, c = myTuple print(a) print(b) print(c)
19.5.1.3. but if you specify more than one variable on left side but that number does not correspond to number of sequence elements, this will raise exception
19.5.1.3.1. myTuple = (4, 5, 6) a, b = myTuple print(a) print(b) print(c)
19.6. Python Tuples
19.6.1. A tuple is an immutable sequence type
19.6.2. syntax to create them uses parentheses ( ) rather than the brackets [ ] used for lists
19.6.2.1. example
19.6.2.1.1. tuple1 = (1, 2, 4, 8) tuple2 = 1., .5, .25, .125
19.6.2.2. you can also create a tuple with just a comma separated element assignment
19.6.2.3. empty tuple assignment allowed, requires empty parentheses ( )
19.6.2.3.1. emptyTuple = ()
19.6.2.4. To create a 1-element tuple, you must put a comma after the element value, otherwise (if you omit comma) the variable will be assigned a single value type, not a tuple
19.6.2.4.1. oneElementTuple1 = (1, ) oneElementTuple2 = 1.,
19.6.3. elements can be mix of any data type, including complex types
19.6.4. For read operations, all the same methods used for lists work the same with tuples
19.6.5. Any attempt to use a list write operation on a tuple will raise an exception
19.6.5.1. myTuple = 1, 2, 3 del myTuple[2] #throws exception myTuple[2] = 4 #throws exception
19.6.5.2. myList = [1, 2, 3] myList.append(4) print(myList) myTuple = (1, 2, 3) myTuple.append(4) #throws exception print(myTuple)
19.6.5.3. but tuples can be deleted as a whole
19.6.5.3.1. del myTuple
19.6.6. You can use the binary + and * operators with tuples and the behaviour is the same as for lists
19.6.6.1. myTuple = 1, 2, 3 myTuple += 4, print(myTuple)
19.6.6.1.1. returns
19.6.6.1.2. note: the += "addition to self" combines two tuples into a new tuple and re-assigns variable to that
19.6.7. You can use the in and not operators with tuples and the behaviour is the same as for lists
19.7. Python Dictionaries
19.7.1. A dictionary is mutable but not a sequence type
19.7.1.1. In Python 3.6x dictionaries have become ordered collections by default.
19.7.2. Elements are key-value pairs
19.7.2.1. key and value are separated by colon
19.7.2.2. key-value pairs are separated by commas
19.7.3. Every key must be unique
19.7.4. Keys can be numbers (int or float) or strings
19.7.5. syntax for assignment uses curly braces { }
19.7.5.1. myE2IDictionary = { "hi" : "ciao", "today" : "oggi", "kiss" : "bacio" }
19.7.6. When keys are string type, they are case-sensitive
19.7.7. Values are retrieved by using keys in same style as list and tuple elements are retrieved via indexes [ key ]
19.7.7.1. dict = {"cat" : "chat", "dog" : "chien", "horse" : "cheval"} print(dict["dog"])
19.7.7.1.1. returns
19.7.7.2. you can also use dictionary get() method
19.7.7.2.1. dict = {"cat" : "chat", "dog" : "chien", "horse" : "cheval"} print(dict.get("dog"))
19.7.8. Key must exist, else exception is thrown
19.7.8.1. dict = {"cat" : "chat", "dog" : "chien", "horse" : "cheval"} print(dict["Dog"])
19.7.8.1.1. throws exception
19.7.8.2. avoid this exception using in or not in operations
19.7.8.2.1. if "horse" in dict: print(dict["horse"]) else: print("horse not in dictionary")
19.7.9. dictionaries can be iterated using for loops, and there are various dictionary methods that can be useful
19.7.9.1. keys()
19.7.9.1.1. dict = {"cat" : "chat", "dog" : "chien", "horse" : "cheval"} for key in dict.keys(): print(key,"->",dict[key])
19.7.9.2. sorted()
19.7.9.2.1. to get a sorted key list, you can use the built in sorted() function
19.7.9.3. items()
19.7.9.3.1. you can also iterate using the items() method, which returns all the key-value pairs as a list of tuples
19.7.9.4. values()
19.7.9.4.1. you can also iterate using the values() method, which returns all the values as a list
19.7.9.5. you can also iterate a dictionary without using any of these methods, as a for loop will naturally iterate all the keys
19.7.9.5.1. dict = {"cat" : "chat", "dog" : "chien", "horse" : "cheval"} for key in dict: print(key,"->",dict[key])
19.7.9.6. when for loop specifies two or more dictionaries to iterate, the loop variable references the whole dictionary rather than the keys
19.7.9.6.1. for example, this code combines two dictionaries together in a third one (d3)
19.7.10. modifying dictionaries
19.7.10.1. update values
19.7.10.1.1. dict['cat'] = "miccio"
19.7.10.1.2. dict.update({'dog' : 'canelino'})
19.7.10.2. add key-value pairs
19.7.10.2.1. dict['snake'] = 'serpente'
19.7.10.2.2. dict.update({'cow' : 'mucca'})
19.7.10.3. delete key-value pairs
19.7.10.3.1. del dict["snake"]
19.7.10.3.2. dict.popitem()
19.7.10.3.3. del dict
19.7.10.3.4. dict.clear()
19.7.11. copying dictionaries with the copy() method
19.7.11.1. copyDict = dict.copy()
20. Python modules
21. Python global keyword and variable scope
21.1. when preceding variable name in a function (or other structure with local scope), enables function to change value of variable that persists outside function body
21.2. for multiple variables, separate each by comma after global password
21.3. example
21.3.1. def myFunction(): global x x = 4 print("x is set inside function") x = 3 myFunction() print(x)
21.3.1.1. returns
21.3.1.1.1. x is set inside function 4
21.4. as general rule, variable declared and assigned in main program has scope inside function body, but variables declared and set inside functions have local scope only
21.4.1. assigning new value to external variable will only affect value inside function unless you previously declare variable inside function body using global keyword
21.4.1.1. del with lists is exception
21.4.1.1.1. x = [5,10] def myFunction(y): print("inside, x =",x) del x[0] print("inside, x =",x) myFunction(x) print("outside, x =",x)
21.4.2. don't try to read external variable and then set it, as you will get exception (local variable referenced before assignment), but global declaration can fix that
21.4.2.1. bad example (throws exception)
21.4.2.1.1. x = 5 def myFunction(y): a = x x = y + 1 print("inside, x =",x) myFunction(x) print("outside, x =",x)
21.4.2.2. good example (no exception)
21.4.2.2.1. x = 5 def myFunction(y): global x a = x x = y + 1 print("inside, x =",x) myFunction(x) print("outside, x =",x)
21.5. you can declare variable inside function with same name as a variable declared outside function, but in this case local variable is treated as separate with local scope only
22. Python function recursion
22.1. Function that invokes itself
22.1.1. example
22.1.1.1. def fib(n): if n < 1: return None if n < 3: return 1 return fib(n - 1) + fib(n - 2) for n in range(1, 10): print(n, "->", fib(n))
22.1.2. recursive invocation should involve reducing the problem towards a base case that solves the problem
22.1.2.1. adding print helps clarify
22.1.2.1.1. failure example (endless loop)
22.1.2.1.2. success example (base case)
22.1.2.2. you will need an if statement to ensure base case is satisfied and recursion ends
22.2. Beware that recursive function calls can consume a lot of memory and care must be taken to avoid endless loop conditions
23. Python mutable and immutable data types
23.1. mutable types allow element values to be changed after initial variable assignment, via index reference - immutable types do not
23.2. immutable types
23.2.1. in-built types like int, float, bool, string, unicode, tuple
23.2.1.1. example
23.2.1.1.1. myString = "Hello" myString[1] = "a"
23.3. mutable types
23.3.1. list, dict, set