Python Advanced 2

programming_language


Selected from Introduciton to Python, authored by Bill Lubanovic
This is the best Python Tutorial that I have ever read.

Chapter 2

Python is strongly typed.
Variables are just names.
Assignment just attaches a name to the object.

Data Types

/ carries out floating-point (decimal) division.
// for integer division.

An "int" can be any size.
Python handles humungous integers with no problem.

Convert a string containing characters that would be a valid float.
float('99') would be 99.0

Python Strings

Strings in Python are immutable.
Duplicate a string with *, such as 'str'*3
Slice with [start: end: step].
Reverse with 'string'[::-1] = 'gnirts'
Combine with join(), the opposite of split().

'string'.startswith('sub')
and
'string'.endswith('sub')
return boolean.

Find the offset of the first occurrence of the word.
'string'.find('i')
Find the last
'string'.rfind('i')
Count
'string'.count('i')

Removing sth from both sides
strip('sth')

Deal with word cases:
capitalize()
title()
upper()
lower()
swapcase()

Deal with alignment within the specific number(like 30) of spaces:
center(30)
ljust(30)
rjust(30)

Chapter 3

Python Lists

Combine lists with extend() or +=
Add an item by offset with insert(offset, item)
Delete an item with del.
del mylist[2]
del is a Python statement: it detaches a name from a Python object and free up the object's memory if that name is the last reference to it.
Delete an item by value with remove(value)

pop(offset) Get an item by offset and delete it at the same time.
pop() pops the last item.

Find the offset of an item by value with index()
mylist.index(item)

Sorting in default ascending order.
mylist.sort() sorts the list itself.
general function sorted() sorts the copy.

Assign with =, Copy with copy()
Three ways to copy:

The list `copy()` function
The `list()` construction function
The list slicing `[:]`

Python Tuples

Tuples let you assign multiple variables at once. (tuple unpacking)
Exchange variables in one statement. a, b = b, a
Goodness of Tuples versus Lists:
1. Tuples use less space.
2. cannot clobber tuple items by mistake.
3. can use tuples as dictionary keys
4. Named Tuples can be a simple alternative to objects.
5. Function arguments are passed as tuples.

Python Dictionaries

use dict() to convert two-value sequence into a dictionary.
dict([['a',1], ['b',2]]) to make {'a':1, 'b':2}

Combine dictionaries with update(). The value from the second dictionary wins when deplication.

Delete an item by key with del.
Delete all item using clear().

Test a key using in
key1 in mydict returns boolean.

Non-thrown item access using get(key, optional_value)
If the key does not exist, the optional value will be returned. If no optional value provided, return None.

Get all keys using keys()
Get all values using values()
Get all key-value pairs using items()

Python Sets

Set Operations:

Set Simbols:
< proper subset, returns boolean
> proper superset
>= or issuperset()

Python lets you do this.
10 < x < 15

Chapter 4

Python considers all these false:
False, None, 0, 0.0, '', [], (), {}, set()

Check break use with else after a while

  1. while cond_satisfied:
  2. do_sth
  3. if cond_hit:
  4. break # jump out of the loop in condiction
  5. else:
  6. print('No break') # execute if break not called

This is the same with "for" loop.

Iterating multiple sequences in parallel with zip().
zip() stops when the shortest sequence is done.
It returns an iterable object.

Generate number sequences with range(start, stop, step)

Comprehension

A comprehension is a compact way of creating a Python data structure from one or more iterators.

Tuples do not have comprehensions!
(expression for expression in iterable)
returns a generator comprehension.
You cannot restart or back up a generator.

Python None

None is a Python value that holds a place when nothing to say.
To detect a None, use if thing is None.

Python functions

specify arguments by the names of their corresponding parameters.
Default values are calculated when the function is defined.

Gather positional argument with *
An asterisk groups a variable number of positional arguments into a tuple of parameter values.

  1. def f(*args):
  2. pass
  3. f(1,2,3,4) # args is (1,2,3,4)

Gather keyword arguments with **
group keyword arguments into a dictionary.

Docstring

  1. def f():
  2. 'this is the docstring of this function'
  3. pass
  4. # to get the docstring
  5. help(f)
  6. print(f.__doc__)

More

Python Functions are the first class citizen.

function.__name__returns the function name.

The main program is assigned the special name __main__.
So the codes below are commonly-seen.

  1. if __name__ == "__main__":
  2. main()

Namespace

A global value can be accessed inside a function but cannot be changed.
To change it, keyword "global" is needed.

  1. x = 1
  2. def f():
  3. global x
  4. x = 2 # x can be changed

locals()/globals() returns a dictionary of the contents of the local/global namespace.

exception

  1. try:
  2. sth.
  3. except IndexError as er:
  4. do_sth
  5. except Exception as others:
  6. do_sth_else

chapter 5

A module is a Python file.

from module import function_name or class_name

import module
module.function()

A package is a file hierachy of organized files.
In the source directory of a package, a file named __init__.py is needed to denote the whole directory as a Python package.

Python Standard Library (STL)

chapter 6

Topics that already learnt:

Get help from parent with super

Once the __init__ function is defined in the sub-class, it overrides the initialization function in the parent class which will not be called automatically anymore.
So the sub-class should call its parant with super.__init__(param)

The use of self

The first argument of class method must be self

Property

Python attributes and methods are all public.
You need to make it private in a Pythonic way.

  1. class HideYourName():
  2. def __init__(self, name):
  3. self.hidden_name = name
  4. def getter(self):
  5. return self.hidden_name
  6. def setter(self, new_name):
  7. self.hidden_name = new_name
  8. # define two methods as properties of attribute "name"
  9. name = property(getter, setter)

In this case, users call with HideYourName('Bob').name as a normal attribute. (But the get/set details are re-defined and the true value 'hidden_name' is hidden but still can be called)

Another way to define properties is to use decorators

  1. @property
  2. def name(self):
  3. return self.hidden_name
  4. @name.setter
  5. def name(self, new_name):
  6. self.hidden_name = new_name

Call as usual.

A property can refer to a computational value.

  1. @property
  2. def diameter(self):
  3. return 2 * self.radius

Call it as c.diameter

The advantage of using properties over direct attribute access: only fix the codes within class if definition of the attribute changed.

Python privacy

A naming convention for attributes that should not be visible outside of the class definition: begin with two underscores.

  1. def __init__(self, name):
  2. self.__hidden = name

You cannot access the hidden attribute with c.__hidden now.
However, this privacy is done by Python with mangling and is not secure at all.
c._ClassName__hidden cross over the getter to visit the private value.

Method types

  1. class C():
  2. cnt = 0
  3. def __init__(self):
  4. C.cnt += 1 # refer to a class attribute
  5. @classmethod
  6. def count(cls): # the class itself
  7. return cls.cnt
  1. @staticmethod
  2. def info():
  3. print('hello')

Duck Typing

A loose implementation of polymorphism - apply the same operation to different objects even if they are different classes.

  1. def who_says(obj):
  2. print(obj.who(), 'says', obj.says())

Any object with these two methods can be called by the function.

Operator overloading with Special methods

  1. __eq__(self, other) # equal
  2. __ne__(self, other) # not equal
  3. __lt__(self, other) # less than
  4. __gt__(self, other) # greater than
  5. __le__(self, other) # less or equal
  6. __ge__(self, other) # greater or equal
  1. __add__(self, other)
  2. __sub__(self, other)
  3. __mul__(self, other)
  4. __floordiv__(self, other)
  5. __truediv__(self, other)
  6. __mod__(self, other)
  7. __pow__(self, other)
  1. __str__(self) # convert the object into a str used by print()
  2. __repr__(self) # used by interpreter echoing
  3. __len__(self)

Tips

Avoid overengineering data structures.
Named tuples are better than objects.
Immutable, time-efficient, access with dot-notation/names, used as dictionary key

  1. from collection import namedtuple
  2. Duck = namedtuple('key1', 'key2')
  3. duck = Duck('value1', 'value2')
  4. duck.key1 # access with dot-notation
  5. duck.key2