Python Language

What is Python

  • This is a Java developer's attempt to learn Python. Python's simplicity is too hard for a Java devleoper!
  • Is an Interpreted language (almost)
  • Variable names are untyped. It is the values they refer to that change type during execution.
  • python is a dynamic language but it is strictly typed. that means adding a string to an int will throw an exception
  • In python everything is an object but in java the primitive types are not.
  • Python does not have variables! everything is a reference

Installation

  1. Download source from python.org and build in Ubuntu
  2. sudo apt-get install build-essential libsqlite3-dev libreadline5-dev libncurses5-dev zlib1g-dev libbz2-dev libssl-dev libgdbm-dev tk-dev (or maybe higher versions in case you get this error: Python build finished, but the necessary bits to build these modules were not found…)
  3. ./configure
  4. make
  5. sudo make install
  6. sudo make clean
  7. This usually goes in /usr/local/bin/python3.x
  8. Install PyDev Eclipse plugin and point it to the above location.
  9. ActiveStatePython is easier to work with. Installing packages with it is much easier. Install packages using "pypm install" command as an admin.
  10. Also we can install setuptools to make use of easy_install tool. pip is also another package installer replacing easy_install.

Basics

  • putting a backslath (\) at the end of the line means we are continuing it to the next line.
  • To place more than one statement on a line, separate the statements with a semicolon
  • identifiers starting with a single underscore such as _foo are not imported by the "from module import *" statement.
  • Identifiers with leading and trailing double underscores such as "_ _init_ _" are reserved for special methods
  • Identifiers with leading double underscores such as __bar are used to implement private class members
  • If the first statement of a module, class, or function definition is a string, that string becomes a documentation string for the associated object.
  • There is no variable declaration. A var is created by using it.
  • When using interactive mode then special variable _ holds the result of the last operation. Try a calculator.
  • '#' for comment
  • In a command line do "pyton test.py" to run. Also we can add #! /usr/bin/python at the start of the code to make it executable.
  • A new line or semicolon terminates a statement
  • Indentation creates blocks of code
  • Single and double quotes are the same for strings and documentation.
  • put # -*- coding: UTF-8 -*- at the beginning of your file to make them understand non-ascii.

References and Copies

a = 5
b=a # b is a copy of a for immutable objects 
 
c = ["1"]
d = a #d is a reference to a for mutable objects. shallow copy
 
import copy
e = copy.deepcopy(a) # to make a deep copy

File

  • read and readline indicate EOF by returning an empty string.
#Read - is similar to open("file", 'r')
f = open("foo.txt")
line = f.readline()
while line:
        print(line)
        line = f.readline()
f.close()
 
#read all the lines into a list    
lines = f.readlines()
for line in lines:
    print(line)
 
# Write'
f = open ("out.txt","w")
print ("ss",file=f) 
#or use f.write
f.close()
 
# read from std in
import sys
p = sys.stdin.readline()
#or
p = input()
# or
p = raw_input()

Modules

  • Adding an import creates a new namespace
  • if a file spam.py defines a class Spam, you must use the name spam.Spam to refer to the class
  • A main module can be identified if its name is main: _ _name_ _ = '_ _main_ _'
  • The top level of the interpreter is the main module. Programs run in command line run inside the _ _main_ _ module.
  • Consider using virtualenv to have separate environments with their own set of libraries different from others…
import pyt # pyt.py is a python file that we import as a module.You can use methods in pyt.py by using pyt prefix.
import div as foo # import as a different name
from pyt import test # just import the test method. now you can use test method directly without pyt. prefix.
from pyt import * #all
import socket, os, re #comma separated
from spam import foo, bar
from spam import (foo,bar,Spam)
 
sys.path.append("mymodules.zip") #add a zip file to the search path
import foo, bar # now will search the zip too
 
sys.path.append("/tmp/modules.zip/lib/python") # mixed of a zip file and path
 
if format == 'xml':
    import xmlreader as reader # import is a first class object and can appear anywhere
 
 __name__ = '__main__'
 
import pyt,sys
print(pyt.__name__)
print(sys.path)
  • Whenever an attribute of a module is referenced (using the dot operator), it’s translated into a dictionary lookup. For example, m.x is equivalent to m._ _dict_ _["x"]. Likewise, assignment to an attribute such as m.x = y is equivalent to m._ _dict_ _["x"] = y.

Other attributes of a module:

m._ _dict_ _ Dictionary associated with the module
m._ _doc_ _ Module documentation string
m._ _name_ _ Name of the module
m._ _file_ _ File from which the module was loaded
m._ _path_ _ Fully qualified package name, only defined when the module object refers to a package

  • The code in each module is loaded and executed only once, regardless of how often you use the import statement.

Styles

See PEP-8. It should be packagename.modulename.ClassName.function_name.var_name

  • Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability.
  • Packages should also have short, all-lowercase names, although the use of underscores is discouraged.
  • Class names should be camel case.
  • Functions/Methods should be lowercase with words separated by underscores as necessary to improve readability
  • Use Space for indentation rather than Tab.

Classes and Objects

Basics

  • () in the class definition indicates inheritance.
  • The first argument in each class method always refers to the object itself (self). All operations involving the attributes of an object must explicitly refer to the self variable.
  • Numbers and string are immutable
class Stack(object):  # Stack inherits from object (root of all)
        a = 5; # class variable
    def _ _init_ _(self): # special method to initialize the stack
        self.stack = [ ]
    def _ _init_ _(self,a): 
        ...
    def push(self,object): 
        self.stack.append(object) 
    def pop(self): 
        return self.stack.pop()
    def length(self):
        return len(self.stack)
    def test(self, a):
        ...
s = Stack() # instantiate the class
s = Stack(4) # calls _ _ init _ _ (self, 4)
s.test(4) 
del s # destroy
 
class Stack(list): # a class inheriting from list
  • Every piece of data stored in a program is an object. In a=4 an integer type is created with the value of 4.
  • The type of an object (instance) is called the object’s class.
  • An attribute is a value associated with an object
  • is operator compares the identity of two objects
def compare(a,b):
    if a is b:
    # a and b are the same object
    if a == b:
    # a and b have the same value
    if type(a) is type(b):
    # a and b have the same type
 
if isinstance(s,list): #instead of  "if type(s) is list"
    ...

Scoping

  • Classes define a namespace but there is no scope for names used inside the bodies of methods. Therefore when you’re implementing a class, references to attributes and methods must be fully qualified using self.
  • The lack of scoping in classes is one area where Python differs from Java.
class Test(object):
    a = 7;
    def tt(self):
        self.a = 6 #referring to a local attribute or method using self.
        print(self.a)
 
    print(a)
 
t = Test() # prints 7
t.tt() # prints 6

Inheritance

  • Python supports multiple inheritance
  • To find attributes with multiple inheritance, all base classes are ordered in a list from the “most specialized” class to the “least specialized” class.
  • When a derived class defines init(), the init() methods of base classes are not automatically invoked.Therefore, it’s up to a derived class to perform the proper initialization of the base classes by calling their init() methods
  • using super() function you can call a method in the base class
  • Whenever an attribute is accessed in an object instance as object_instance.attr, attr is located by searching in the following order. The first match will be returned:
    1. within the instance itself
    2. the instance’s class definition
    3. and then base classes in order
class Account(object):
    pass
 
class Account2(object):
    pass
 
class Test(Account, Account2):
    def __init__(self,name,balance,xyz):
        Account.__init__(self,name,balance) # Initialize Account manually
        ...
    pass

Special Methods

All basic interpreter operations are implemented through special object methods.The names of special methods are always preceded and followed by double underscores (_ _).These methods are automatically triggered by the interpreter as a program executes. For example, the operation x + y is mapped to an internal method, x._ _add_ _(y), and an indexing operation, x[k], is mapped to x._ _getitem_ _(k).The behavior of each data type depends entirely on the set of special methods that it implements.

Object creation/destruction

class Test(object):
    def __del__(self):
        print("self")
    def __init__(self):
        print("init")
    def testm(self):
        print("testm method")
 
t = Test()
t.testm()
 
#output :
#    init
#    testm method
#    self
 
# calling A(args) is equal to A._ _new_ _(A,args)

Object String representation

# implement the following in your class which is similar to Java's toString:
 
def __str__( self ):
        return ...
 
a = [2,3,4,5]
s = repr(a) # s = '[2, 3, 4, 5]' repr() returns an expression string that can be evaluated to re-create the object
b = eval(s) # Turns s back into a list
  • str() It differs from _ _repr_ _() in that the string it returns can be more concise and informative to the user.

Object comparison and order

  • If you want to be able to compare objects using == or use an object as a dictionary key, the _ _eq_ _() method should be defined. If you want to be able to sort objects or use functions such as min() or max(), then _ _lt_ _() must be defined.

_ _bool_ _(self) Returns False or True for truth-value testing
_ _hash_ _(self) Computes an integer hash index
_ _lt_ _(self,other) self < other
_ _le_ _(self,other) self <= other
_ _gt_ _(self,other) self > other
_ _ge_ _(self,other) self >= other
_eq_ _(self,other) self == other
_ _ne_ _(self,other) self != other

Static

  • A static method is an ordinary function that just happens to live in the namespace defined by a class.
class EventHandler(object):
    @staticmethod
    def dispatcherThread():
        ...
EventHandler.dispatcherThread() # Call method like a function

I it much like a static method in a Java class.

Methods

Methods are functions that are defined inside a class definition.There are three types of methods—instance methods, class methods, and static methods.

class Foo(object):
 
    # operates on an instance of a given class. The instance is passed via self.
    def instance_method(self,arg): 
        statements
 
    # operates on the class itself as an object.
    @classmethod 
    def class_method(cls,arg): 
        statements
 
    # A static method is just a function that happens to be packaged inside a class
    @staticmethod
    def static_method(arg): 
        statements
f = Foo()
callable_m = f.instance_method  #lookup the method. there is no call operator: ()
callabe_m(4) # callable_m is a bound method
 
m = Foo.instance_method # no (). m is called unbound method
m(f,4) # call but supply self.
  • A bound method is a callable object that wraps both a function (the method) and an associated instance.
  • An unbound method is a callable object that wraps the method function, but expects self.

Attributes of method objects:

m._ _doc_ _ Documentation string
m._ _name_ _ Method name
m._ _class_ _ Class in which this method was defined
m._ _func_ _ Function object implementing the method
m._ _self_ _ Instance associated with the method (None if unbound)

  • Built-in functions (len()) and methods (x.append where x is a list) have some attributes too; such as: _ _ doc_ _, _ _ self_ _, _ _ name_

property

  • A property is a special kind of attribute that computes its value when accessed. The @property decorator makes it possible for the method that follows to be accessed as a simple attribute, without the extra () that you would normally have to add to call the method.
class Circle(object):
    def __init__(self,radius):
        self.radius = radius
 
    @property
    def area(self):
        return math.pi*self.radius**2
 
c = Circle(4.0)
print(c.area)

First class objects

All objects in Python are said to be first class.

items = {"number" : 44,
         "aa" : abs
         }
print(items['aa'](44))

Callable Interface

An object can emulate a function by providing the _ _call_ _(self [,args]) method. If an object, x, provides this method, it can be invoked like a function.That is, x(arg1, arg2, …) invokes x._ _call_ _(self, arg1, arg2,…). Objects that emulate functions can be useful for creating functors or proxies.

class DistanceFrom(object):
    def _ _init_ _(self,origin):
        self.origin = origin
    def _ _call_ _(self, x):
        return abs(x - self.origin)
 
DistanceFrom(10)

Private Attributes

All names in a class that start with a double underscore, such as _ _Foo, are automatically changed to form a new name of the form _Classname_ _Foo. This has less visibility than public.

class A(object):
    def __init__(self):
        self.__X = 3 #  is changed to to self._A__X
    def __spam(self): # is changed to _A__spam()
        pass
    def bar(self):
        self.__spam() # Only calls A.__spam()

Abstract Base Class (abc)

  • An abstract class is not meant to be instantiated directly.
  • Although an abstract class enforces rules about methods and properties that must be implemented, it does not perform conformance checking on arguments or return values
  • Although an abstract class can not be instantiated, it can define methods and properties for use in subclasses
  • An abstract method in the base can still be called from a subclass
from abc import ABCMeta, abstractmethod, abstractproperty
class Foo(metaclass=ABCMeta): 
    @abstractmethod
    def spam(self,a,b):
        print("in base spam") #can have impl
 
    @abstractproperty
    def name(self):
        pass # can have impl
 
#a  = Foo() # this is an error
 
class NoFoo(Foo):
    def spam(self,a,b):
        print("in NoFoo spam")
 
    def test(self):
        Foo.spam(3,4) # calling an abstract method in super class
 
    # does not implement the abstract property so is still abstract
 
#a = NoFoo() # error    
 
class YesFoo(NoFoo):
    def test(self):
        Foo.spam(self,3,4) #Can call parent
 
    def spam(self,a,b):
        print("in NoFoo spam")
 
    def name(self): print("name of no foo")
 
a = YesFoo()
a.test() #works!

Types

None

Is a null object and evaluates to False in boolean expressions. This object is returned by functions that don’t explicitly return a value so it similar to void in java too.

Sequences

str(Character string-immutable), unicode, list, tuple (immutable), xrange([i,]j [,stride]), range in py3.

String

  • Use triple quote for multiple line texts.
  • Strings are stored as sequences of characters indexed by integers, starting at zero
  • Most of the methods operating on string do not modify the string a return a new one
  • To extract a substring, use the slicing operator s[i:j]
  • convert to numeric using int(s) or float(t);
  • convert non-string to string using str(s) or repr or format
  • String is immutable
  • Strings are compared using lexicographical ordering
  • String formatting: print "%3d %0.2f %s" % (year, principal,name) for int, float and string.

List

  • Lists are indexed by integers, starting with zero
  • all(s): Checks whether all items in s are True.
  • any(s): Checks whether any item in s is True
  • functions applicable to a list: count, append, extend, remove, sort, pop, insert, …
  • Is mutable
  • Sequences are compared using the operators <, >, <=, >=, ==, and !=
names = [ "Dave", "Mark", "Ann", "Phil" ]
names[2] # Negative indices can be used to fetch characters from the end of a sequence; s[-1] returns the last item
names[0:2] # extract/slicing i<= [i:j] < j
names[2:]
del name[0:2] # delete slice
a[1::2] = [10,11] # a = [1,10,3,11,5]
list(s) # converts any iterable to a list. if s is already a list then it will shallow copy it
names.append("Paula") # append to the end
names.insert(2, "Thomas") # insert
a=[1,2,3] + [4,5] #concat
min(a)
max(a)
len(a)
 
a=[] #empty list
b=list() # empty list
n = [1,"Dave",3.14, ["Mark", 7, 9, [100,101]], 10]
n[3][3][1] #returns 101

Tuple

  • Used to create simple data structures
  • Tuples support most of the same operations as lists
  • The contents of a tuple cannot be modified after creation (immutable) and use less memory compared to lists
stock = ('GOOG', 100, 490.10)
stock = 'GOOG', 100, 490.10 # no bracket
a = () # 0-tuple (empty tuple)
b = (item,) # 1-tuple (note the trailing comma)
c = item, # 1-tuple (note the trailing comma)
 
# loop
portfolio = ((1,2,3),(4,5,6))
for name, shares, price in portfolio:
    print(name)

Numbers

  • (immutable) int, long, float, complext, bool (True 1, False 0)
  • There is no double in python

Map

Dictionary (hash table) or dict. Some of its methods are: clear, copy, get, items, keys, pop, popitem, update, values, …

stock = {
    "name" : "GOOG",
    "shares" : 100,
    "price" : 490.10
}
 
name = stock["name"] #access by key
stock["shares"] = 75 #insert
prices = {} # An empty dict
prices[1,2,3] = "foo"
prices = dict() # An empty dict
 
if "SCOX" in prices:
    p = prices["SCOX"]
else:
    p=0
 
#Above code this is equivalent to :
p = prices.get("SCOX",0.0) # if key exists then the value is returned otherwise 0.0 will be its value
 
syms = list(prices) # To obtain a list of dictionary keys, convert a dictionary to a list
 
del prices["MSFT"] # del statement removes an element of the dict
 
a = { (a,'1') : 3} # a tuple as the key of the dictionary

Set

  • set(mutable), frozenset(immutable)
  • Use set() function to create an unordered, un-duplicated collection of objects
  • Unlike lists and tuples, sets are unordered and cannot be indexed by numbers.
s = set([3,5,9,10]) # Create a set of numbers
t = set("Hello") # Create a set of unique characters
a = t | s # Union of t and s
b = t & s # Intersection of t and s
c = ts # Set difference (items in t, but not in s)
d = t ^ s # Symmetric difference (items in t or s, but not both)
t.add('x') # Add a single item
s.update([10,37,42]) # Adds multiple items
t.remove('H') # remove item
  • set is a mutable set, and frozenset is an immutable set
  • Items in a set are immutable
  • More methods: issubset, issuperset, union, copy, difference,

Operators and Expressions

  • Expression x<y<z is legal
  • dot is attribute operator and and () is function call operator
  • Conditional expression: (is like Ternary Conditional Operator in Java) minvalue = a if a <=b else b
  • There is no ++

Unpacking

items = [ 3, 4, 5 ]
x,y,z = items # x = 3, y = 4, z = 5
letters = "abc"
x,y,z = letters # x = 'a', y = 'b', z = 'c'
datetime = ((5, 19, 2008), (10, 30, "am"))
(month,day,year),(hour,minute,am_pm) = datetime

Conversion Functions

  • To convert between types, you simply use the type name as a function: int(x), str(x), set(x), …

Boolean

  • a = True
  • Empty lists, tuples, and dictionaries evaluate as false
  • x or y, x and y, not y

Operations in sequences

s + r Concatenation
s * n, n * s Makes n copies of s, where n is an integer
v1,v2…, vn = s Variable unpacking
s[i] Indexing
s[i:j] Slicing
s[i:j:stride] Extended slicing
x in s, x not in s Membership
for x in s: Iteration
all(s) Returns True if all items in s are true.
any(s) Returns True if any item in s is true.
len(s) Length
min(s) Minimum item in s
max(s) Maximum item in s
sum(s [, initial]) Sum of items with an optional initial value

Equality

The equality operator (x == y) tests the values of x and y for equality. The identity operators (x is y and x is not y) test two objects to see whether they refer to the same object in memory. In general, it may be the case that x == y, but x is not y.

in Operator

Is used for strings, list, dictionary, etc.

s= "aaaliddd"
if("ali") in s:  
    print("a")

Functions

  • Functions are first-class objects. They can be passed as arguments to other functions, placed in data structures, and returned by a function as a result
  • User-defined functions are callable objects created at the module level by using the def statement or with the lambda operator.
  • You can use a tuple to return multiple values from a function (using a tuple)
  • Functions can accept a default arg value. When a function defines a parameter with a default value, that parameter and all the parameters that follow are optional when calling the function. see below.
  • A function can accept a variable number of parameters if an asterisk (*) is added to the last parameter name: def fprintf(file, fmt, *args). In this case, all the remaining arguments are placed into the args variable as a tuple.
  • Function arguments (not params) can also be supplied by explicitly naming each parameter and specifying a value: foo(x=3, z=[1,2]). These are known as keyword arguments.
  • If the last argument of a function definition begins with ** then all the additional keyword arguments (those that don’t match any of the other parameter names) are placed in a dictionary and passed to the function in a dict: def test(a, **parms).
  • We can combine extra keyword arguments with variable-length argument lists, as long as the ** parameter appears last: def a(*a, **b)
  • global statement is used in a function method to make a variable accessible outside of the function.
  • We can have nested functions (def inside def)
  • Functions can be passed as arguments to other functions
  • Variables in nested functions are bound using lexical scoping.That is, names are resolved by first checking the local scope and then all enclosing scopes of outer function definitions from the innermost scope to the outermost scope. If no match is found, the global and built-in namespaces are checked as before.
  • The nonlocal declaration does not bind a name to local variables defined inside arbitrary functions further down on the current call-stack (dynamic scope).
  • An inner function can’t reassign the value of a local variable defined in an outer function
def divide(a,b):
    q = a // b # If a and b are integers, q is integer
    r = a - q*b
    global s = 6 # accessible outside of function with global statement
    return (q,r) # return multiple values in a tuple
 
result = divide(37,15) #return multiple values in a tuple
x, y = divide(1243,4) # assign multiple values directly
 
quotient, remainder = divide(1456,33) #unpack result of a function
 
def connect(hostname,port,timeout=300): #default value 300 for a param
connect('www.python.org', 80) # default value can be omitted from a function call
connect(port=80,hostname="www.python.org") # call with name
 
#default value example
a = 10
def foo(x=a): #default value
    return x
a = 5 # Reassign 'a'.
foo() # returns 10 (default value not changed)
 
#variable args
def write_data(file,data, *args):
    print(file,data,args)
write_data(None, "a", "c", "d")     # None a ('c', 'd')
 
# Keyword argument invocation
def foo(w,x,y,z):
    statements
foo(x=3, y=22, w='hello', z=[1,2]) #order does not matter
 
# using ** in function definition
def write_data(file,data, **args):
    print(file,data,args)
write_data(file=None, data="a",x="c", y="d")    # None a {'y': 'd', 'x': 'c'}
 
# pass a function as a param
def callf(func):
    return func()
 
# local variable
def write_data(file,data):
    n = 7
    print("inside outer")
    def test():
        n = 8 #local to test()
        print("inside inner n=" + str(n))
    test()
    print(n)
write_data("a","b")
 
>>inside outer
>>inside inner n=8
>>7
 
#nonlocal variable
def write_data(file,data):
    n = 7
    print("inside outer")
    def test():
        nonlocal n # Bind to outer n (Python 3)
        n = 8 
        print("inside inner n=" + str(n))
    test()
    print(n)
write_data("a","b")
 
>>inside outer
>>inside inner n=8
>>8
 
# Accept variable number of positional or keyword arguments
def spam(*args, **kwargs):
    # args is a tuple of positional args
    # kwargs is dictionary of keyword args

Variable Scope

a = 42
def foo():
    a = 13 # a is in local function namespace
foo()
# a is still 42
 
# another example:
a = 42
b = 37
def foo():
    global a  #a is in global namespace 
    a = 13
    b = 0
foo()
# a is now 13. b is still 37

Function Attributes

def foo():
    statements
foo.secure = 1
foo.private = 1

Common built-in attributes of a user defined function f:

f._ _doc_ _ Documentation string
f._ _name_ _ Function name
f._ _dict_ _ Dictionary containing function attributes
f._ _code_ _ Byte-compiled code
f._ _defaults_ _ Tuple containing the default arguments
f._ _globals_ _ Dictionary defining the global namespace
f._ _closure_ _ Tuple containing data related to nested scopes

  • Be careful when using decorators and function attributes.

lambda operator

  • Anonymous functions in the form of an expression can be created using the lambda statement: lambda args : expression
  • The primary use of lambda is in specifying short callback functions
  • One of the points in lambda calculus is that functions do not necessarily need names
a = lambda x,y : x+y
r = a(2,3) # 5
 
names.sort(key=lambda n: n.lower())

Closure

  • When a function is handled as data, it implicitly carries information related to the surrounding environment where the function was defined.This affects how free variables in the function are bound.
  • When the statements that make up a function are packaged together with the environment in which they execute, the resulting object is known as a closure. In pyton functions are closure (in the below example "helloworld" is a closure)
  • All functions have a _ _globals_ _ attribute that points to the global namespace in which the function was defined in. This always corresponds to the enclosing module in which a function was defined.
  • When nested functions are used, closures capture the entire environment needed for the inner function to execute
  • Closures and nested functions are useful in lazy or delayed evaluation
#Example 1
# foo.py
x = 42
def callf(func):
    return func()
 
# foo2.py
import foo
x = 37
def helloworld():
    return "Hello World. x is %d" % x
 
# Pass a function(helloworld) as an argument. It takes its environment with it!
foo.callf(helloworld) # prints 'Hello World. x is 37'
 
# Example 2 with nested functions
import foo
def bar():
    x = 13
    def helloworld():
        return "Hello World. x is %d" % x
    foo.callf(helloworld) # returns 'Hello World, x is 13'
 
# Example 3 
from urllib import urlopen
# from urllib.request import urlopen (Python 3)
def page(url): # page just creates and returns the get function
    def get():
        return urlopen(url).read()
    return get # until get is called later in the code the read() is delayed.
 
python = page("http://www.python.org")
a = python() # does the actual read()

Decorator

  • The @ symbol is used to define a decorator
  • A decorator is a function whose primary purpose is to wrap another function or class. The primary purpose of this wrapping is to transparently alter or enhance the behavior of the object being wrapped.
  • Decorator returns a function
  • Decorator concept is closely related to closure.
#Example 1
def addmore(func):
    def inner(x):
        return func(x) + 4;
 
    return inner
 
@addmore
def add(x):
    return x+1
 
print(add(4)) # returns 9
 
#The general form is:
@decorator
def func(x):
    pass
 
#this decorator code is equivalent to:
def func(x):
    ...
 
func = decorator(func) #func() is a closure that serves as a replacement for the original function
 
def decorator(f):
    ....
    return f;
 
#applying more than one decorate in order:
@foo
@bar
@spam
def grok(x):
    pass
 
#is equivalent of
def grok(x):
    pass
grok = foo(bar(spam(grok)))
  • Decorators can also be applied to class definitions
  • Decorators can accept arguments
  • Wrapping a function with a decorator can break the help features associated with documentation strings; see wraps function.

Generator

  • Any function that uses yield is known as a generator
  • Calling a generator function creates an object that produces a sequence of results through successive calls to a next() method (or _ _next _ _() in Python 3); Remember iterators in Java.
  • The next() call makes a generator function run until it reaches the next yield statement. At this point, the value passed to yield is returned by next(), and the function suspends execution.The function resumes execution on the statement following yield when next() is called again.This process continues until the function returns.
  • Generators usages: processing pipelines, streams, data flow, Iterators, …
def countdown(n):
    print("Counting down!")
    while n > 0:
        yield n # returns n
        n -= 1
 
c= countdown(3) # returns a generator object. No code is executed.
print(c.__next__()) # Prints "Counting down!" and returns 3. Generator function executes statements until it reaches a yield statement
print(c.__next__()) # returns 2. Execution resumes with the statement following yield...
 
c.close() # closes a generator midway before completion
 
# yield can be used in the following ways (where ever functions consume a sequence)
for n in countdown(10):
    statements
a = sum(countdown(10))

Coroutine

  • Normally, functions operate on a single set of input arguments. However, a function can also be written to operate as a task that processes a sequence of inputs sent to it.This type of function is known as a coroutine and is created by using the yield statement as an expression (yield).
  • In coroutines yield is used as an expression in the right side of an assignment as opposed to generators.
  • The behaviour of coroutine is similar to generators.
  • Coroutine runs in response to values being sent to it but generator runs in response to a call to the next() method.
  • To use a coroutine:
    1. You first call it
    2. then advance it to the first (yield) with next()
    3. Then start sending data to it using send()
    4. A coroutine is suspended at (yield) until a value is sent to it. When this happens, that value is returned by the (yield) expression and the processing continues by the statements that follow.
    5. Processing continues until the next (yield) expression is encountered (where the function suspends) or close().
def print_matches(matchtext):
    print("Looking for " + matchtext)
    while True:
        line = (yield) # Get a line of text
        if matchtext in line:
            print(line)
 
matcher = print_matches("python") #get the coroutine.
matcher.__next__() # advance to the first yield and suspend
matcher.send("Hello World") # this new value is give to (yield) and we move on
matcher.send("python is cool")
 
# another example
def receiver():
    print("Ready to receive")
    while True: # this loop is needed. otherwise it will throw exception when exits.
        n = (yield)
        print(n)
 
r = receiver()
r.__next__() # prints "Ready to receive" and waits for a send(). This first call to the "next" is necessary.
r.send("reza")
r.send("ali")
 
# output:
>> Ready to receive
>> reza
>> ali
  • Coroutines are useful in concurrent programs based on producer-consumer pattern where the coroutine will be the consumer of data.
  • Coroutines usually run indefinitely unless it is explicitly shut down (close method) or it exits on its own
# another example to put the initial call to the next() into a decorator
 
def coWrapper(func):
    def start(*args,**kwargs):
        g = func(*args,**kwargs)
        g.__next__()
        return g
    return start
 
@coWrapper
def receiver():
    print("Ready to receive")
    while True:
        n = (yield)
        print(n)
 
r = receiver()
#r.__next__()
r.send("reza")
r.send("ali")

List Comprehension

Is used to apply a function to all of the items of a list, creating a new list with the results.

# the general form of it is:
 
[expression for x in iterable1 if condition1
    for y in iterable2 if condition2
    ...
    for z in iterableN if conditionN ]
 
#for example
a=[1,2,3,4]
c = [2*s for s in a]
print(c) # prints [2, 4, 6, 8]

Generator Expression

  • Is similar to list comprehension but uses parentheses instead of square brackets and iteratively generates the results using next() method.
  • It creates a generator object that produces the values on demand via iteration.
# the general form of it is:
 
(expression for x in iterable1 if condition1
    for y in iterable2 if condition2
    ...
    for z in iterableN if conditionN)
 
#for example
a=[1,2,3,4]
c = (2*s for s in a)
print(c._ _next_ _()) # prints 2
 
# Generator expression can save memory and improve performance. 
# The following example does not read the whole file but find and prints comments in it:
f = open("x.txt") # Open a file
lines = (t.strip() for t in f) # Read lines, strip trailing/leading whitespace on demand not all at onece
comments = (t for t in lines if t[0] == '#') # All comments - again on demand.
for c in comments: # this is where the lines are actually read !
    print(c)
 
# Reads a two column file and adds the columns - very compact code
lines = open("x.txt")
fields = (line.split() for line in lines)
print(sum(float(f[0]) + float(f[1]) for f in fields))
  • Unlike a list comprehension, a generator expression does not create an object that works like a sequence. It can’t be indexed, and none of the usual list operations will work. However, a generator expression can be converted into a list using the list() function.

Recursion

  • There is a limit on the depth of recursive function calls.The function sys.getrecursionlimit() returns the current maximum recursion depth, and the function sys.setrecursionlimit() can be used to change the value.The default value is 1000. When the recursion depth is exceeded, a RuntimeError exception is raised and we are always limited to the stack size anyway.
  • Java on the other hand does not have a limit similar to Python but you might hit the memory roof and get an out of memory error.

Structure and Flow

Conditions

if b == 4 or b ==6 and not b==3:
    print("ss")
elif b == 9:
    print(50)
else:
   raise RuntimeError("err")
 
# shortening a condition
 
if a <= b:
    minvalue = a
else:
    minvalue = b
 
#This code can be shortened using a conditional expression. For example:
 
minvalue = a if a <=b else b
 
# now see this :
 
values = [1, 100, 45, 23, 73, 37, 69 ]
clamped = [x if x < 50 else 50 for x in values] # see list comprehension
 
line = f.readline()
if not line:
    stmt
 
# instead of if s == "" or if s == null
if s:
    pass

Loop

  • for can iterate over many kinds of objects including strings, lists, dictionaries, and files
  • break and continue also work in Python similar to Java
  • for loop in python is actually a for-each iterator
for line in open("foo.txt"):
    print line
 
#Creating a new list of float - list comprehension
fvalues = [float(i) for i in iValues]
 
for n in [1,2,3,4,5,6,7,8,9]: # is equivalent to for n in range(1,10):
    ...
 
while expression:
    statements    
 
a = [[1,2,3], [4,5,6]]
for x,y,z in a:    #if a contains sequences of identical size we can unpack it like this
    print(x)   # outputs 1 and 4
 
# keeping track of the index:
i = 0
for x in s:
    statements
    i += 1
 
# the above code is equivalent of: 
 
for i,x in enumerate(s):
    statements
 
# iterating in parallel over two or more sequences
for x,y in zip(s,t):  # s and t are two sequences
    statements
 
#for-else
for ...:
    statement
else: #called after for is finished. if for is terminated with break it will be skipped.
    ...
s = '''
sdfsdfsdff
'''
print(s)
print(s[2])
print(s[1:5])
 
fields = line.split(",") # Split the string 'line' into a list
  • More methods: capitalize, count, center, decode, encode, find, rfind, format, isalnum, isdigit, islower, replace, index, rindex,split, rsplit, …

Exceptions

  • SystemExit(1)
try:
    ....
except:
    ...
else:    #is executed if the code in the try block doesn’t raise an exception
    ....
finally:  #similar to java
    ...
 
# how to use it
try:
    f = open("file.txt","r")
except IOError as e:  # similar to catch in java
    print (e)
    p = sys.exc_info() # more info on the stack trace. this has more useful attributes
 
# to raise (throw) exception
raise RuntimeError("Computer says no") # similar to throw in Java
 
# to catch multiple types
except (IOError, TypeError, NameError) as e:
    ...
 
# to ignore an exception
exceot IPError
    pass
 
 # catch all exceptions except those related to program exit. 
except Exception as e:  
    ...
 
# catch all exceptions - not good to use
except: 
   ...
  • define a custom exception by inheriting from Exception : class NewExcepiton(Exception): pass

Context management - with

  • The with statement allows a series of statements to execute inside a runtime context that is controlled by an object that serves as a context manager.
  • The with obj statement allows the object to manage what happens when control-flow enters and exits the associated block of statements that follows.
  • It only works with objects that support the context management protocol (the _ _enter_ _() and _ _exit_ _() methods)
with open("debuglog","a") as f:
    f.write("Debugging\n")
    statements
    f.write("Done\n")
 
#add support for context-management with "with"
class ListTransaction(object):
    def _ _init_ _(self,thelist):
        self.thelist = thelist
    def _ _enter_ _(self):
        self.workingcopy = list(self.thelist)
        return self.workingcopy
    def _ _exit__(self,type,value,tb):
        if type is  None:
        self.thelist[:] = self.workingcopy
        return False

assert

  • Assert statement should be used to check things that should always be true; if one is violated, it represents a bug in the program.
def write_data(file,data):
    assert file, "write_data: file not defined!"
 
write_data(None, "a")  # this will throw an AssertionError with the specified message.  
 
assert False, "hi"

Regular Expressions

import re
re.findall(r'[0-5]',"4")

r before the regex means raw and should sit before any regex.

Web

See Python Web

List of functions

See Function List

Reference

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License