My Python Notes

Everything is object, including class
Everything has namespace
Everything can be printed / retrospected
Functions are first class object
They can be passed as arguments to other functions,
returned as values from other functions, and
- assigned to variables and stored in data structures.

In Python values carries types
In Python variables do not carry types

Variables means reference to object
Always object reference is passed to function

PyPy : Run time environment

Python supports
* Multiple inheritence
* mixins
* extensive introspection of type and class
* operator overloading with special member function
* complex numbers
* limited support to lambda


Module = Statements + Definitions
Few important modules are: 
OS : System calls. enviorn for env variables like $HOME. it is dictionary.
sys : to get argv. e.g. sys.argv[1:] because argv[0] is programe name
string, regex, collections, heapq, array, enum, etc. 
numbers, decimals and  fractions : For extra numeric types

Package is default constructor for the package. 

from package import module

Package is a folder, that contains (1) file (2) 1+ .py files as modules. (3) optionally contains another folder as package. 

Type conversion:
Moderatly type checked language
Implicit conversion for numeric types
No implicit conversion between string and number

Switch = if ... elif ... elif ... else

* Base Types
String is immutable. So replacing a char, returns new String object. 

* Collection (container) Types

Objects can be easily refernced or indexed

A. Sequence : ordered type

1. String = immutable 

String Format

print("I just printed %s pages to the printer %s" % (num, printer))
print("I just printed {0} pages to the printer {1}".format(num, printer))
print("I just printed {num} pages to the printer {printer}".format(num=num, printer=printer))
print(f"I just printed {num} pages to the printer {printer}")

""" OR ''' are used for multiline string

space, coma and newline are default delimiter used in split
x = input("Prompt message"). here x will be always string. 

2. Lists = mutable, dynamic array. 

List has in-build functions like : sort, len, append(one member), remove (value is argument), To delete entry from list at specific index, use : "del list[index]". insert, extend (list), index, pop = pop(-1) (index is argument), no push function.   
List declaration: a_list = [1, 2, "asdf"] OR a_list = list()
comprehension is like lembda function.
primes = [2] 
e.g. list2 = [x ** 2 for x in list1]
Here primes is list with member 2

By Reference
L1 = [1, 2, 3]
L2 = L1

To make duplicate copy of list
L2 = L1[:]

3. Tuples = immutable.

Tuple declaration: a_tuple = 1, 2, "asdf" OR a_tuple = (1, 2, "asdf")
Tuples are also good for storing closely related data. For example, (x, y, z) coordinates or (r, g, b) colour components. Tuples are records without field name. So order of values and number of fields are very important. It is like ASN.1 encoded byte stream. The actual variable name is defined somewhere in RFC.  So number of field and sequence of values are very important. 

B. Mapping : un-ordered type

1. Dictionaries = Associative Array. Keys are immutable. So String and Tuples can be keys.
Dictionary declaration: dict = {k1:v1, k2:v2}
Useful for JSON objects. 
Dictionary has built-in functions like : has_key(key), get(key, 'optional unknown'), keys, values, del dict['key'], update function will merge the value part: if key found then change value else add the pair.  Two dictionary can be merged with update, for duplicate key

>>> x = {'a': 1, 'b': 2}
>>> y = {'b': 3, 'c': 4}

>>> z = {**x, **y}

>>> z
{'c': 4, 'a': 1, 'b': 3}

one can get list containing keys from dictionary. a_list = list(a_dict)

.set_default() is also important function
defaultdict is function at collections module. It will set default value, when key is added for first time. 

>>> student_grades = defaultdict(list)
>>> for name, grade in grades:
...     student_grades[name].append(grade)

Here, list create an empty list. 
if name key is added to first time, then it will be added with value as empty list []

2. Set : no duplicate. no order, 
Set declaration : a_set = {0, (), "asdf", False}
Set has built-in functions like  : union |, intersection &, difference, symmetric difference -, union - intersection = ^, and subset testing

x = {} This is empty dic not empty set. 

3. Frozenset : immutable set

To iterate through all collection, one can use: 
for item in
The built-in function type() allows us to obtain the type of any object.

Python code compilation to : 

1. CPython : code -> Python byte code
2. Jython : code -> Java Byte Code
3. IronPython : code -> IL(.NET) Byte code

Variable scope

1. local scope
2. global scope
3. built-in scope

* string, number, sequence, map all can be compared
* a < b < c = (a < b) && (b < c)

The core built-in types for manipulating binary data are bytes and bytearray. They are supported by memoryview, which uses the buffer protocol to access the memory of other binary objects without needing to make a copy.

To activate any virtual enviornment
source venv/bin/activate

It can be created with below steps

pip install virtualenv
sudo /usr/bin/easy_install virtualenv
cd robot-tests
virtualenv venv
source ./venv/bin/activate
pip install


inside class, function is called "class method"
inside class, variable is called "member variable"

"this" in Java, is "self" in Python. "self" can be replaced with another name. it should be first argument. Inside method, object variables can be accessed using self

One more method type, where we pass cls. Here with cls, we can access class member. 

__init__ is constructor
__del__ is destructor
If we have two __init__ function in the class. Then last one will override all earlier __init__ functions.

For inheritance, parent class is passed as input. Obejct is parent class of all. 

At abstract class add @abstractmethod decorator,
Abstract class should be child of ABC

private member start with __

To build iterator class, we need two methods: 
1. __iter__
2. next
in addition to __init__

Generator is just a function. Not Class. It should have yield statement. It returns the iterator object. 

lambda is a one line nameless/anonymous function in python

It is used in map, filter, list comprehension etc. 

map (function, iterable)
map is a special function. 
it returns iterable
The first argument 'function' can be lambda or any other built-in function name like 'str'

filter function. input is predicate. predicate is a condition check. 

itertools module has map, filter, accumulation, count, repeat, permutation, products etc. 

@class it replace the constructor. 

we can have custom decorator as method 

list comprehension

If 2 functions calls each other recursively then also it is recursive function

raise is to stop programme, when error happens

print("%r") can be used, when we are not sure about integer, or string. 

  • instead of "if condition" use dictionary
  • instead of "loop" use "try catch"
  • for re-usability, write code in class. 
  • add documentation 
  • Use _ for variables, you don’t care about. It is just a convention.
  • The * operator allow us to capture remaining items after an unpacking into a list. For example
head, middle, tail = number[0], number[1:-1], number[-1]
head, *middle, tail = number 
  • Python 2 variables can be swapped with this code
a, b = b, a

  • Debugging in Python

# Some complicated code with bugs
        import pdb; pdb.set_trace()

        • Counter from collections module is useful for word count. input is string. it crates dictionary of word as key and count as value. 
        • This common string group is also useful

          • string.ascii_letters
          • string.ascii_uppercase
          • string.ascii_lowercase
          • string.digits
          • string.hexdigits
          • string.octdigits
          • string.punctuation
          • string.printable
          • string.whitespace

        Singleton design pattern