python core notes

Upload: jacob-riddle

Post on 01-Jun-2018

238 views

Category:

Documents


2 download

TRANSCRIPT

  • 8/9/2019 Python Core Notes

    1/191

     

    Page 1of 191

    g

     

    ArPython

    Version 1.1.7 20 Februrary 2007

    Contents

    References ......................................................................................................................................... 4

    Overview ............................................................................................. Error! Bookmark not defined. 

    Python language essentials ................................................................................................................ 4

    Lexical structure ............................................................................................................................. 4

    Objects ........................................................................................................................................... 5

    Names ........................................................................................................................................ 7

    Assignment ................................................................................................................................. 7

    lists .............................................................................................. Error! Bookmark not defined. 

    Dictionaries ................................................................................. Error! Bookmark not defined. 

    sets ........................................................................................................................................... 15

    Flow control ................................................................................................................................. 17

    while ......................................................................................................................................... 17

    for ............................................................................................................................................. 17

    iterators and generators .......................................................................................................... 25

    list comprehensions ................................................................................................................. 32

  • 8/9/2019 Python Core Notes

    2/191

     

    Page 2of 191

    g

    With .......................................................................................................................................... 33

    Functions ...................................................................................................................................... 43

    Classes .......................................................................................................................................... 50

    Why Decorate? ........................................................................................................................ 58

    Creating Decorators ................................................................................................................. 59

    Objects as Decorators .............................................................................................................. 59

    Stacking Decorators ................................................................................................................. 60

    Functions as Decorators .......................................................................................................... 61

    Decorators with Arguments ..................................................................................................... 62

    Function Attributes .................................................................................................................. 63

    Practicing "Safe Decs" .............................................................................................................. 63

    Putting It All Together .............................................................................................................. 64

    Conclusion ................................................................................................................................ 66

    Modules, Packages, paths and imports ........................................................................................... 74

    Setting import path of a module to any directory ....................................................................... 74

    Notes on .pth files ........................................................................................................................ 75

    Documentation ................................................................................................................................ 75

    Pydoc ............................................................................................................................................ 75

    Docutils ........................................................................................................................................ 75

    Distributions of Python Software .................................................................................................... 75

    The Working Set ........................................................................................................................... 77

    The Environment .......................................................................................................................... 77

    Python Eggs .................................................................................................................................. 78

    Initialization, Development, and Deployment ............................................................................. 78

  • 8/9/2019 Python Core Notes

    3/191

     

    Page 3of 191

    g

    Disutils .......................................................................................................................................... 80

    Conversion to Executables ............................................................................................................... 80

    PyInstaller .................................................................................................................................... 80

    Py2exe .......................................................................................................................................... 81

    Recipe for plain python (console) ............................................................................................ 81

    Recipe for wxpython (windows) .............................................................................................. 82

    How does py2exe work and what are all those files? ............................................................. 82

    CGI .................................................................................................................................................... 84

    CGI Web Applications with Python, Part One.............................................................................. 86

    Opening word documents from Python ........................................................................................ 107

    Quick receipt .............................................................................................................................. 107

    more detailed receipt ................................................................................................................ 107

    Printing word files ...................................................................................................................... 108

    Patterns .......................................................................................................................................... 109

    Typology ..................................................................................................................................... 109

    mvc ......................................................................................................................................... 119

    DQueues ......................................................................................................................................... 119

    deque objects ........................................................................................................................... 119

    Recipes ................................................................................................................................... 123

    Heap queue .................................................................................................................................... 125

    Event scheduler .............................................................................................................................. 130

    Mutual exclusion support .............................................................................................................. 131

    Coroutines and Threading ............................................................................................................. 132

    Threading ................................................................................................................................... 132

  • 8/9/2019 Python Core Notes

    4/191

     

    Page 4of 191

    g

    Queue ....................................................................................................................................... 133

    Python threads - a first example ............................................................................................ 135

    THE SAME APPLICATION, WRITTEN USING PYTHON THREADS ............................................. 137

    Understanding Threading in Python .......................................................................................... 141

    My own coroutine stuff ............................................................................................................. 166

    Module threadpool .................................................................................................................... 177

    APPENDIX: Type Hierarchy ............................................................................................................. 177

    Basic date and time types .............................................................................................................. 188

    Decimal floating point arithmetic .................................................................................................. 190

    References

    PyERef Python Essential Reference (Beazley)

    PyNut "Python in a Nutshell 2nd

     ed" by Alex Martelli

    PyCBK Python cookbook 2nd

     ed " by Alex Martelli

    PyLib Python 2.5 library

    PracPy Practical Python

    PyTut Python 2.5 Tutorial

    PyLib Python 2.5 Library

    Python language essentials

    Lexical structure  logical lines (consisting of one or more physical lines) with indentation of contiguous to

    denote blocks of statements. Each indentation level uses four spaces. Tabs are replaced

    by up to 8 spaces. Best is to expand automatically tabs to spaces when editing.

      Character set is ascii per default; other character sets are allowed if the first comment

    defines the codec (utf-8 or iso-8859-1) with the following coding directives:

  • 8/9/2019 Python Core Notes

    5/191

     

    Page 5of 191

    g

     

    # -*- coding:utf-8 -*-

    or

    # encoding: utf-8

      Tokens are elementary lexical components resulting as breakup of a logical line:

    identifiers, keywords, operators, delimiters, literals

    A source file is a sequence of simple and compound statements. The former lies entirely within a

    logical line and can be an expression or assignment. The latter controls one or more other

    statements and controls their executions, by means of one or more clauses. A clause has a

    header of the form :  and a body made out of a single or a block of statements.

    ObjectsAll data values are objects, having a

      Type, which determines which operations are supported, as well as the attributes

    (properties) and items associated to the object (for instance, methods –as covered

    later on) and whether the object´s value can be altered (mutability).

      Unique identity, which is an integer that corresponds to the object´s location in

    memory

      Content ( also called value)

    An object that contains references to other objects is said to be a container or collection.

  • 8/9/2019 Python Core Notes

    6/191

     

    Page 6of 191

    g

    Some objects allow you to change their content  (without changing the identity or the type, that

    is). Some objects don't allow you to change their content (more below).

    You cannot change the identity.

    You cannot change the type. Actually, this is quite subtle:

    The type is represented by a type object, which knows more about objects of this type

    (how many bytes of memory they usually occupy, what methods they have, etc).( actually,

    you can change the type under  some rather limited circumstances1.)

    1 so you can in fact change the type, as long as the internal structure (the "C-level type") is

    identical. the types involved must (to quote the checkin messages):

    - have the same basic size

    - have the same item size

    - have the same dict offset

    - have the same weaklist offset

    - have the same GC flag bit

    - have a common base that is the same except for maybe the

    dict and weaklist (which may have been added separately at

    the same offsets in both types)

    - both be heap types

    this basically limits the feature to classes defined at the Python level (just like before the

    unification); most attempts to use arbitrary types will fail. e.g.

    >>> x.__class__ = dict

    Traceback (most recent call last):

    File "", line 1, in ?

    TypeError: __class__ assignment: only for heap types

    http://article.gmane.org/gmane.comp.python.general/427452http://article.gmane.org/gmane.comp.python.general/427452http://article.gmane.org/gmane.comp.python.general/427452http://article.gmane.org/gmane.comp.python.general/427452

  • 8/9/2019 Python Core Notes

    7/191

     

    Page 7of 191

    g

     

    Objects may also have this:

      zero or more methods (provided by the type object)  zero or more names

    Some objects have methods that allow you to change the contents of the object (modify it in place, that is).

    Some objects only have methods that allow you to access the contents, not change it. Some objects don't have any

    methods at all. Even if they have methods, you can never change the type, nor the identity.

    Things like attribute assignment and item references are just syntactic sugar (more below).

    Names

    The names are a bit different  —  they're not really properties of the object, and the object itself doesn't know what it's

    called. An object can have any number of names, or no name at all.

    Names live in namespaces (such as a module namespace, an instance namespace, a function's local namespace).

    Namespaces are collections of (name, object reference) pairs (implemented using dictionaries).

    When you call a function or a method, its namespace is initialized with the arguments you call it with (the names are

    taken from the function's argument list, the objects are those you pass in).

    Assignment

     Assignment statements modify namespaces, not objects. In other words,

    name = 10 

    >>> class c(list):

    ... pass

    ...

    >>> x.__class__ = c

    Traceback (most recent call last):

    File "", line 1, in ?

    TypeError: __class__ assignment: 'a' object layout differs from 'c'

  • 8/9/2019 Python Core Notes

    8/191

     

    Page 8of 191

    g

    means that you're adding the name "name" to your local namespace, and making it refer to an integer object containing

    the value 10.

    If the name is already present, the assignment replaces the original name:

    name = 10

    name = 20 

    means that you're first adding the name "name" to the local namespace, and making it refer to an integer object

    containing the value 10. You're then replacing the name, making it point to an integer object containing the value 20.

    The original "10" object isn't affected by this operation, and it doesn't care.

    In contrast, if you do:

    name = []

    name.append(1) 

    you're first adding the name "name" to the local namespace, making it refer to an empty list object. This modifies the

    namespace. You're then calling a method on that object, telling it to append an integer object to itself. This modifies the

    content of the list object, but it doesn't touch the namespace, and it doesn't touch the integer object.

    Things like name.attr  and name[index]  are just syntactic sugar for method calls. The first corresponds to

     __setattr__/ __getattr__, the second to __setitem__/ __getitem__ (depending on which side of the assignment they

    appear).

    The built-in object() returns a bland object , which is the abstract base class for all classes and

    objects.

    Types may be built-in or user defined. Built-in types are:

      None

      Numbers int,long,float,complex,bool

      Sequences list,tuple,str,xrange,unicode,basestring

      Mapping dict

      Sets set,frozenset

  • 8/9/2019 Python Core Notes

    9/191

     

    Page 9of 191

    g

      Callable object, types… (see Appendix) 

      Modules types.ModuleType

      Classes object

      Types type

      Files file

      Internal types…. (see Appendix) 

      Classic Classes types.ClassType , types.InstanceType

    The built-in type(obj) accepts any object as argument and returns the type object that is the type

    of obj (built in or in the types module). Be aware of the polyphormic feature of the type built-in,

    that also accepts the form type(name,bases,dict) to create a new type object (same as defining a

    new class).

    t=(1,2,3)

    l=[1,2,3]

    d=dict(a=1,b=2)

    s=set()

    class C: pass

    class Cnew(object): pass

    def name(x): return x.__name__

    print "type: %s" %type(1)

    print "type: %s" %type("")

    print "type: %s" %type(l)

    print "type: %s" %type(t)

    print "type: %s" %type(s)

    print "type: %s" %type(d)

  • 8/9/2019 Python Core Notes

    10/191

     

    Page 10of 191

    g

    print "type: %s" %type(object)

    print "type: %s" %type(name)

    print "type: %s" %type(C)

    print "type: %s" %type(Cnew)

    emits:

    type:

    type:

    type:

    type:

    type:

    type:

    type:

    type:

    type:

    type:

    The attributes associated to an object may be retrieved using the dir() built-in. Some objects have

    the attribute __name__, like classes, while others do not. Some objects allow that the __name__

    attribute be set –in particular the user defined objects.

    For instance,

    def setName(obj,x):

    obj.__name__=str(x)

    def getName(x):

  • 8/9/2019 Python Core Notes

    11/191

     

    Page 11of 191

    g

      return x.__name__

    c=C()

    #c.__name__='my name is c'

    #setName(c,'my name is bim bam bola')

    print "name: %s" %getName(C)

    print "name: %s" %getName(c)

    #emits:

    name: C

    Traceback (most recent call last):

    … 

    File "D:\Python\lib\dump.py", line 47, in getName

    return x.__name__

     AttributeError: 'C' object has no attribute '__name_

    However, if any of the comments setting name is enabled:

    #emits:

    name: C

    name: my name is bim bam bola

    There are objects that do not allow to set the __name__ attribute, like built-in types (as lists): you

    get the following error when trying to do that on a list l=[1,2,3]:

    Traceback (most recent call last):

  • 8/9/2019 Python Core Notes

    12/191

     

    Page 12of 191

    g

    … 

    l.__setattr__('__name__','hallo')

     AttributeError: 'list' object has no attribute '__name__'

    and dir(l) renders:

    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__',

    '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',

    '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__

    ', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',

    '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append','count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 

    a similar thing happens with a dictionary or a set

    ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__',

    '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__',

    '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduc

    e_ex__', '__repr__', '__setattr__', '__setitem__', '__str__', 'clear', 'copy', 'fromkeys', 'get',

    'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault',

    'update', 'values']

  • 8/9/2019 Python Core Notes

    13/191

     

    Page 13of 191

    g

     

    The following test script renders interesting results:

    #testattributes.py

    #class L(object,list):# would raise TypeError: Error when calling the metaclass bases

    # Cannot create a consistent method resolution order (MRO) for bases

    object, list

    class L(list):

    pass

    l=L([1,2,3])

    x=l.pop()

    print l

    print dir(L)#does not return attribute __name__ although it exists

    print L.__name__

    #L.__setattr__(L,'__name__','ANTONIO')# would raise: TypeError: can't apply this

    __setattr__ to type object

    #l.__setattr__('__name__','ANTONIO')#would raise: AttributeError: 'list' object has no

    attribute '__name__'

    #print l.__name__# would raise: AttributeError: 'L' object has no attribute '__name__'

    l.__dict__['__name__']='antonio' #works

    print l.__name__

    Li=[1,2,3]

    print dir (Li)

    #print Li.__name__ #would raise: attributeError: 'list' object has no attribute

    '__name__'

    #Li.__dict__['__name__']='antonio'#would raise: attributeError: 'list' object has no

    attribute '__dict__'

  • 8/9/2019 Python Core Notes

    14/191

     

    Page 14of 191

    g

    """

    results:

    [1, 2]

    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__',

    '__dict__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__',

    '__getslice__',

    '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__',

    '__len__',

    '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',

    '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__',

    '__str__', '__weakref__', 'append', 'count', 'extend', 'index', 'insert', 'pop',

    'remove', 'reverse', 'sort']

    L

    antonio

    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__',

    '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__',

    '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__',

    '__len__',

    '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',

    '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__',

    '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse',

    'sort']

    """

    Data values (objects) are accessed through references, which is a name that refers to the location

    in memory, taking the form of variables, object attributes and items.

    A name is bound to an object through an assignment statement (name=value in a simplified form

    or more generically target=expression) . Generically, the target may be an identifier , an

    attribute reference (obj.name, whereby name is here an attribute name of the object), an

    indexing (obj[expr]) or a slicing (obj[start:stop:stride]).

  • 8/9/2019 Python Core Notes

    15/191

     

    Page 15of 191

    g

     

    References may be unbound using a del statement, followed by one or more taget references.

    Objects can be (arbitrarily) categorized as

      collections

    o  lists

    o  dictionaries

    o  sets

    sets

    A set  object is an unordered collection of immutable values. Common uses include membership

    testing, removing duplicates from a sequence, and computing mathematical operations such as

    intersection, union, difference, and symmetric difference.

    Like other collections, sets support  x  in set , len(set ), and for x  in set . Being an unordered collection,

    sets do not record element position or order of insertion. Accordingly, sets do not support

    indexing, slicing, or other sequence-like behavior.

    There are currently two builtin set types, set and frozenset. The set type is mutable -- the

    contents can be changed using methods like add() and remove(). Since it is mutable, it has

    no hash value and cannot be used as either a dictionary key or as an element of another set. The

    frozenset type is immutable and hashable -- its contents cannot be altered after is created;

    however, it can be used as a dictionary key or as an element of another set.

    set( [iterable]) 

  • 8/9/2019 Python Core Notes

    16/191

     

    Page 16of 191

    g

    return a set whose elements are taken from iterable. The elements must be immutable.

    To represent sets of sets, the inner sets should be frozenset objects. If iterable is not

    specified, returns a new empty set, set([]). 

    Instances of set and frozenset provide the following operations:

    Operation  Equivalent Result 

    len(s)  cardinality of set s 

     x  in s  test x  for membership in s 

     x  not in s  test x  for non-membership in s 

    s.issubset(t )  s = t   test whether every element in t  is in s 

    s.union(t )  s | t   new set with elements from both s and t  

    s.intersection(t )  s & t   new set with elements common to s and t  

    s.difference(t )  s - t   new set with elements in s but not in t  

    s.symmetric_difference(t ) s ^ t   new set with elements in either s or t  but not both

    s.copy()  new set with a shallow copy of s 

  • 8/9/2019 Python Core Notes

    17/191

     

    Page 17of 191

    g

     

    Flow controlA program's control flow is the order in which the program's code executes. The control flow of a

    Python program is regulated by conditional statements, loops, and function calls.

    Conditionan and loop control flow statements are: if, while, for .

    while

    The while statement in Python supports repeated execution of a statement or block of

    statements that are controlled by a conditional expression. Here's the syntax for the while statement:

    while expression:

    statement(s)

    A while statement can also include an else clause

    for

    The for statement in Python supports repeated execution of a statement, or block of statements,

    controlled by an iterable expression. Here's the syntax for the for statement:

    for target in iterable:

    statement(s)

    The in keyword is part of the syntax of the for statement and is distinct from the in operator,

    which tests membership. A for statement can also include an else clause.

    iterable may be any Python expression suitable as an argument to built-in function iter, which

    returns an iterator object ( is covered below ). In particular, any sequence is iterable.

    target is normally an identifier that names the control variable of the loop; the for statement

    successively rebinds this variable to each item of the iterator, in order.

  • 8/9/2019 Python Core Notes

    18/191

     

    Page 18of 191

    g

     The statement or statements that make up the loop body execute once for each item in

    iterable (unless the loop ends because an exception is raised or a break or return statement

    executes). Note that, since the loop body may contain a break statement to terminate the loop,

    this is one case in which you may want to use an unbounded iterable-one that, per se, would

    never cease yielding items.

    You can also have a target with multiple identifiers, as with an unpacking assignment. In this case,

    the iterator's items must then be iterables, each with exactly as many items as there are

    identifiers in the target.

    Some interesting comments:

    understanding Python's "for" statement

    One of the things I noticed when skimming through the various reactions to my recent "with"-article

    is that some people seem to have a somewhat fuzzy understanding of Python's other block

    statement, the good old for-in loop statement. The with statement didn't introduce code blocks in

    Python; they've always been there. To rectify this, for-in probably deserves it's own article, so here

    we go (but be warned that the following is a bit rough; I reserve the right to tweak it a little over the

    next few days).

    On the surface, Python's for-in statement is taken right away from Python's predecessor ABC, 

    where it's described as:

    FOR name,... IN train:

    commands

    Take each element of train in turn

    In ABC, what's called statements in Python are known as commands, and sequences are known as

    trains. (The whole language is like that, by the way; lots of common mechanisms described using

    less-common names. Maybe they thought that renaming everything would make it easier for people

    to pick up the subtle details of the language, instead of assuming that everything worked exactly as

    other seemingly similar languages, or maybe it only makes sense if you're Dutch.)

    http://online.effbot.org/2006_10_01_archive.htm#withhttp://homepages.cwi.nl/~steven/abc/http://homepages.cwi.nl/~steven/abc/http://online.effbot.org/2006_10_01_archive.htm#with

  • 8/9/2019 Python Core Notes

    19/191

     

    Page 19of 191

    g

     Anyway, to take each element (item) from a train (sequence) in turn, we can simply do (using a

    psuedo-Python syntax):

    name = train[0]

    do something with name

    name = train[1]

    do something with name

    name = train[2]

    do something with name

    ... etc ...

    and keep doing that until we run out of items. When we do, we'll get an IndexError exception, which

    tells us that it's time to stop.

     And in its simplest and original form, this is exactly what the for-in statement does; when you write

    for name in train:

    do something with name

    the interpreter will simply fetch train[0] and assign it to name, and then execute the code block. It'll

    then fetch train[1], train[2], and so on, until it gets an IndexError.

    The code inside the for-in loop is executed in the same scope as the surrounding code; in the

    following example:

    train = 1, 2, 3

    for name in train:

    value = name * 10

    print value

    the variables train, name, and value all live in the same namespace.

  • 8/9/2019 Python Core Notes

    20/191

     

    Page 20of 191

    g

    This is pretty straightforward, of course, but it immediately gets a bit more interesting once you

    realize that you can use custom objects as trains. Just implement the __getitem__ method, and you

    can control how the loop behaves. The following code:

    class MyTrain:

    def __getitem__(self, index):

    if not condition:

    raise IndexError("that's enough!")

    value = fetch item identified by index

    return value # hand control back to the block

    for name in MyTrain():

    do something with name

    will run the loop as long as the given condition is true, with values provided by the custom train. In

    other words, the do something part is turned into a block of code that's being executed under the

    control of the custom sequence object. The above is equivalent to:

    index = 0

    while True: # run forever

    if not condition:

    break

    name = fetch item identified by index

    do something with name

    index = index + 1

    except that index is a hidden variable, and the controlling code is placed in a separate object.

    You can use this mechanism for everything from generating sequence elements on the fly (like

    xrange):

  • 8/9/2019 Python Core Notes

    21/191

     

    Page 21of 191

    g

    class MySequence:

    def __getitem__(self, index):

    if index > 10:

    raise IndexError("that's enough!")

    return value * 10 # returns 0, 10, 20, ..., 100

    and fetching data from an external source:

    class MyTable:

    def __getitem__(self, index):

    value = fetch item index from database table

    if value not found:

    raise IndexError("not found")

    return value

    or from a stream:

    class MyFileIterator:

    def __getitem__(self, index):

    text = get next line from file

    if end of file:

    raise IndexError("end of file")

    return text

    to fetching data from some other source:

    class MyEventSource:

    def __getitem__(self, index):

    event = get next event

    if event == terminate:

    raise IndexError

    return event

    for event in MyEventSource():

  • 8/9/2019 Python Core Notes

    22/191

     

    Page 22of 191

    g

      process event

    It's more explicit in the latter examples, but in all these examples, the code in __getitem__ is

    basically treating the block of code inside the for-in loop as an in-lined callback.

     Also note how the last two examples don't even bother to look at the index; they just keep calling

    the for-in block until they run out of data. Or, less obvious, until they run out of bits in the internal

    index variable.

    To deal with this, and also avoid the issue with having objects that looks a lot as sequences, but

    doesn't support random access, the for-in statement was redesigned in Python 2.2. Instead of using

    the __getitem__ interface, for-in now starts by looking for an __iter__ hook. If present, this method

    is called, and the resulting object is then used to fetch items, one by one. This new protocol

    behaves like this:

    obj = train.__iter__()

    name = obj.next()

    do something with name

    name = obj.next()

    do something with name

    ...

    where obj is an internal variable, and the next method indicates end of data by raising the

    StopIterator exception, instead of IndexError. Using a custom object can look something like:

    class MyTrain:

    def __iter__(self):

    return self

    def next(self):

    if not condition:

    raise StopIteration

    value = calculate next value

    return value # hand control over to the block

  • 8/9/2019 Python Core Notes

    23/191

     

    Page 23of 191

    g

     

    for name in MyTrain():

    do something with name

    (Here, the MyTrain object returns itself, which means that the for-in statement will call MyTrain's

    own next method to do the actual work. In some cases, it makes more sense to use an independent

    object for the iteration).

    Using this mechanism, we can now rewrite the file iterator from above as:

    class MyFileIterator:

    def __iter__(self):

    return self # use myself

    def next():

    text = get next line from file

    if end of file:

    raise StopIteration()

    return text

    and, with very little work, get an object that doesn't support normal indexing, and doesn't break

    down if used on a file with more than 2 billion lines.

    But what about ordinary sequences, you ask? That's of course easily handled by a wrapper object,

    that keeps an internal counter, and maps next calls to __getitem__ calls, in exactly the same way

    as the original for-in statement did. Python provides a standard implementation of such an object,

    iter, which is used automatically if __iter__ doesn't exist.

    This wasn't very difficult, was it?

    Footnote: In Python 2.2 and later, several non-sequence objects have been extended to support

    the new protocol. For example, you can loop over both text files and dictionaries; the former return

    lines of text, the latter dictionary keys.

    for line in open("file.txt"):

  • 8/9/2019 Python Core Notes

    24/191

     

    Page 24of 191

    g

      do something with line

    for key in my_dict:

    do something with key

  • 8/9/2019 Python Core Notes

    25/191

     

    Page 25of 191

    g

     

    iterators and generators

    Interesting objects are iterators and generators.

    To iterate means to repeat something several times- what you do with loops. In Python you can

    iterate over special objects, iterators, representing a stream of data and returning the data one

    element at a time. It must support a method called next() always returning the next element

    of the stream: you can only go forward and there is no way to get the previous element.

    Formally, an iterator  is an object i such that you can call i.next( ) with no arguments.

    i.next( ) returns the next item of iterator i or, when iterator i has no more items, raises a

    StopIteration exception. The built-in iter() function takes an arbitrary object and tries to

    return an iterator that will return the object´s contents or elements raising TypeError if the

    object does not support iteration. An object is said to be iterable if you can get an iterator for it.

    Any Python sequrence type (lists, tuples, strings) as well as dictionaries are iterable – they will

    automatically support creation for an iterator. When you write a class you can allow instances of

    the class to be iterators by defining a method next and the attribute __iter__().

    Iterators can be built by implicit or explicit calls to built-in function iter. Calling a generator

    also returns an iterator.

    Notice that after consuming all of the iterator´s output the iterator is exhausted: if you need to

    do something different with the same stream, you need to create a new (different) iterator.

    L= [1,2,3]; C= (1,2,3); S= set(L) ; D= dict(x=1,y=2,z=3)

    class K:

    def __init__(self,values):

    self.values=values

    def next(self):

    try:

    return self.values.pop()

    except:

    raise StopIteration

    def __iter__(self):

    return self

    k=K(L)

  • 8/9/2019 Python Core Notes

    26/191

     

    Page 26of 191

    g

    X=k

    it1 = iter(X)

    print it1

    for item in it1: print item

    print it1.next()

    emits the following, since the last statement referred to an exhausted iterator :

    3

    2

    1

    Traceback (most recent call last):

    File "D:\Python\TESTS\test.py", line 24, in

     print it1.next()

    File "D:\Python\TESTS\test.py", line 13, in next

    raise StopIteration

    StopIteration

    The situation does not change making the following change:

    for item in it1: print item

    it1 = iter(X) # does not change anything – the iterator is exhausted!

    print it1.next()

    The following file  provides iterator tests.

    http://localhost/var/www/apps/conversion/tmp/TESTS/itertests.pyhttp://localhost/var/www/apps/conversion/tmp/TESTS/itertests.pyhttp://localhost/var/www/apps/conversion/tmp/TESTS/itertests.py

  • 8/9/2019 Python Core Notes

    27/191

     

    Page 27of 191

    g

    A generator2 is a function whose body contains one or more occurrences of the keyword yield.

    When the generator is called, the function body does not execute: instead, it returns a special

    2 Generators and iterators are related to the concept of coroutines. Coroutines are more generic than subroutines.

    The start of a subroutine is the only point of entry; the start of a coroutine is the first point of entry, and places

    within a coroutine following returns (yields) are subsequent points of entry. Subroutines can return only once; in

    contrast, coroutines can return (yield) several times. The lifespan of subroutines is dictated by last in, first out (the

    last subroutine called is the first to return); in contrast, the lifespan of coroutines is dictated entirely by their use and

    need.

    Here's a simple example of how coroutines can be useful. Suppose you have a consumer-producer relationship

    where one routine creates items and adds them to a queue and another removes items from the queue and uses

    them. For reasons of efficiency, you want to add and remove several items at once. The code might look like this:

    var  q := new queue

    coroutine produce

    loop 

    while q is not full

    create some new items

    add the items to q

    yield to consume

    coroutine consume

    loop 

    while q is not empty

    remove some items from q

    use the items

    yield to produce

    Each coroutine does as much work as it can before yielding control to the other using the yield  command. The yield  

    causes control in the other coroutine to pick up where it left off, but now with the queue modified so that it can do

    more work. Although this example is often used to introduce multithreading, it's not necessary to have two threads to

    effect this dynamic: the yield  statement can be implemented by a branch directly from one routine into the other.

    http://en.wikipedia.org/wiki/LIFOhttp://en.wikipedia.org/wiki/LIFOhttp://en.wikipedia.org/wiki/LIFOhttp://en.wikipedia.org/wiki/Multithreadinghttp://en.wikipedia.org/wiki/Multithreadinghttp://en.wikipedia.org/wiki/Multithreadinghttp://en.wikipedia.org/wiki/Multithreadinghttp://en.wikipedia.org/wiki/LIFO

  • 8/9/2019 Python Core Notes

    28/191

     

    Page 28of 191

    g

    iterator object that wraps the function body, its local variables (including its parameters) and

    the current point of execution, which is initially the start of the function; when the next method

    of this iterator object is called, the function body executes up to the next yield statement (yield

    expression). At this point, the function execution is frozen, with current point of execution and

    local variables intact, and the expression following yield is returned as the result of the next

    method. When next is called again, execution of the function body resumes where it left off,again up to the next yield statement. If the function body ends or executes a return statement,

    the iterator raises a StopIteration exception, to indicate that the iteration is finished. Return

    should have no parameters3. A generator may be unbounded (returning an infinite stream o

    results) or bounded. In Python 2.5 a generator object has the methods send, throw and close.

    Python's generators provide a convenient way to implement the iterator protocol. If a container

    object's __iter__() method is implemented as a generator, it will automatically return an iterator

    object (technically, a generator object) supplying the __iter__() and next() methods.  

    One framework for coroutines is spasmodic, supporting asynchronous I/O (and other tasks). The SpasmodicEngine

    selects tasks (spasmoids) from a (heapqueue based) priority queue. The tasks are Python 2.5 extended generators

    (some call them coroutines: PEP 342).

    The engine calls task.send() with an appropriate argument. One of the library of tasks is Pollster. Pollster calls poll()

    with for tasks that are waiting I/O. Tasks that are ready for I/O are fed to the priority queue.

    Spasmodic provides an efficient way to manage a large number of sockets and/or files. Other processing works welltoo, if it can be subdivided into brief spasms.

    3 def updown(N):

    """ small generator function"""

    for x in xrange(1, N): yield x

    if x==3: return 5

    for x in xrange(N, 0, -1): yield x

    for i in updown(4): print I

    renders:

    >>> File "", line 4 SyntaxError: 'return' with argument inside generator

  • 8/9/2019 Python Core Notes

    29/191

     

    Page 29of 191

    g

    The for statement implicitly calls iter to get an iterator. The following statement:

    for x in c:

    statement(s) 

    is exactly equivalent to:

     _temporary_iterator = iter(c)

    while True:

    try: x = _temporary_iterator.next( )

    except StopIteration: break

    statement(s) 

    where _temporary_iterator  is some arbitrary name that is not used elsewhere in the current scope.

    Thus, if iter(c) returns an iterator i such that i.next( ) never raises StopIteration (an unbounded

    iterator ), the loop for x  in c never terminates (unless the statements in the loop body include suitable

    break or return statements, or raise or propagate exceptions). iter(c), in turn, calls special method

    c._ _iter_ _( ) to obtain and return an iterator on c.

    Many of the best ways to build and manipulate iterators are found in standard library module

    itertools.

    while and for statements may optionally have a trailing else clause. The statement or block

    under that else executes when the loop terminates naturally (at the end of the for iterator, or

    when the while loop condition becomes false), but not when the loop terminates prematurely

    (via break, return, or an exception). When a loop contains one or more break statements, you

    often need to check whether the loop terminates naturally or prematurely. You can use an else 

    clause on the loop for this purpose:

    for x in some_container:

    if is_ok(x): break # item x is satisfactory, terminate

    loop

    else:

    print "Warning: no satisfactory item was found in container"

    x = None

  • 8/9/2019 Python Core Notes

    30/191

     

    Page 30of 191

    g

    any and all built-in functions in Python 2.5 

    $ python2.5

    Python 2.5 (r25:51908, Sep 27 2006, 12:21:46)

    [GCC 3.3.5 (Debian 1:3.3.5-13)] on linux2

    Type "help", "copyright", "credits" or "license" for more information.

    >>> any

    built-in function any

    >>> all

    built-in function all

    >>> print any.__doc__

    any(iterable) -> bool

    Return True if bool(x) is True for any x in the iterable.

    >>> print all.__doc__

    all(iterable) -> bool

    Return True if bool(x) is True for all values x in the iterable.

    >>> any([1,2])

    True

    >>> all([1,2])

    True

    >>> any([1,0])

    True

  • 8/9/2019 Python Core Notes

    31/191

     

    Page 31of 191

    g

    >>> all([1,0])

    False

  • 8/9/2019 Python Core Notes

    32/191

     

    Page 32of 191

    g

    list comprehensions

    A common use of a for loop is to inspect each item in an iterable and build a new list by

    appending the results of an expression computed on some or all of the items. The expression

    form known as a list comprehension lets you code this common idiom concisely and directly.Since a list comprehension is an expression (rather than a block of statements), you can use it

    wherever you need an expression (e.g., as an argument in a function call, in a return statement,

    or as a subexpression for some other expression).

    A list comprehension has the following syntax:

    [ expression for target in

    iterable lc-clauses ]

    target and iterable are the same as in a regular for statement. You must enclose the

    expression in parentheses if it indicates a tuple.

    lc-clauses is a series of zero or more clauses, each with one of the following forms:

    for target in iterable 

    if expression 

    target and iterable in each for clause of a list comprehension have the same syntax and

    meaning as those in a regular for statement, and the expression in each if clause of a list

    comprehension has the same syntax and meaning as the expression in a regular if statement.

    A list comprehension is equivalent to a for loop that builds the same list by repeated calls to theresulting list's append method. For example (assigning the list comprehension result to a variable

    for clarity):

    result1 = [x+1 for x in some_sequence]

    is the same as the for loop:

    result2 = []

    for x in some_sequence:

    result2.append(x+1)

    Here's a list comprehension that uses an if clause:

    result3 = [x+1 for x in some_sequence if x>23]

    This list comprehension is the same as a for loop that contains an if statement:

    result4 = []

    for x in some_sequence:

  • 8/9/2019 Python Core Notes

    33/191

     

    Page 33of 191

    g

      if x>23:

    result4.append(x+1)

    And here's a list comprehension that uses a for clause:

    result5 = [x+y for x in alist for y in another]

    This is the same as a for loop with another for loop nested inside:

    result6 = []

    for x in alist:

    for y in another:

    result6.append(x+y)

    As these examples show, the order of for and if in a list comprehension is the same as in the

    equivalent loop, but in the list comprehension, the nesting remains implicit.

    With

    The with statement is used to wrap the execution of a block with functionality provided by a

    separate guard object (see context-managers). This allows common try-except-finally usage

    patterns to be encapsulated for convenient reuse.

    from __future__ import with_statement # To enable in 2.5

    Syntax:

    with expression [as target ] : 

    suite 

    or:

    with expression [as ( target list  ) ] : 

    suite 

    The expression is evaluated once, and should yield a context guard , which is used to control

    execution of the suite. The guard can provide execution-specific data, which is assigned to the

    target (or target list).

    Note that if a target list is used instead of a single target, the list must be parenthesized.

    Here's a more detailed description:

    http://pyref.infogami.com/context-managershttp://pyref.infogami.com/context-managershttp://pyref.infogami.com/context-managershttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/syntax-suitehttp://pyref.infogami.com/syntax-targethttp://pyref.infogami.com/syntax-expressionhttp://pyref.infogami.com/context-managers

  • 8/9/2019 Python Core Notes

    34/191

     

    Page 34of 191

    g

    1.  The context expression is evaluated, to obtain a context guard .

    2.  The guard object's  __enter__ method is invoked to obtain the context entry value.

    3.  The context entry value is assigned to the target or target list, if present.

    4.  The suite is executed.

    5.  No matter what happens in the suite, the guard object's  __exit__ method is invoked.

    If an exception caused the suite to be exited, its type, value, and traceback are passed

    as arguments to  __exit__. Otherwise, three None arguments are supplied.

    If the suite was exited due to an exception, and the return value from the  __exit__ method is

    false, the exception is reraised. If the return value is true, the exception is suppressed, and

    execution continues with the statement following the with statement.

    If the suite was exited for any reason other than an exception (e.g., by falling off the end of

    the suite, or via return, break, or continue), the return value from  __exit__ is ignored, and

    execution proceeds at the normal location for the kind of exit that was taken.

    Note: The with statement guarantees that if the  __enter__ method returns without an error,

    then  __exit__ will always be called. Thus, if an error occurs during the assignment to the

    target list, it will be treated the same as an error occurring within the suite would be. See

    step 5 above.

    Note: In Python 2.5, the with statement is only allowed when the with_statement feature

    has been enabled. It will always be enabled in Python 2.6. This  __future__ import statement

    can be used to enable the feature (see future):

    from __future__ import with_statement

    See Also: PEP 0343, The "with" statement  The specification, background, and examples for

    the Python with statement.

    with statement considered hard?

    The documentation to context managers. The term comes from the draft documentation but

    doesn't explain it further. From that draft:

    Context managers ensure a particular action is taken to establish the context before the

    contained suite is entered, and a second action to clean up the context when the suite is exited.

    and from the PEP

    the actual state modifications made by the context manager

    http://pyref.infogami.com/__enter__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/Nonehttp://pyref.infogami.com/Nonehttp://pyref.infogami.com/Nonehttp://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/returnhttp://pyref.infogami.com/returnhttp://pyref.infogami.com/returnhttp://pyref.infogami.com/breakhttp://pyref.infogami.com/breakhttp://pyref.infogami.com/breakhttp://pyref.infogami.com/continuehttp://pyref.infogami.com/continuehttp://pyref.infogami.com/continuehttp://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/with_statementhttp://pyref.infogami.com/with_statementhttp://pyref.infogami.com/with_statementhttp://pyref.infogami.com/__future__http://pyref.infogami.com/__future__http://pyref.infogami.com/__future__http://pyref.infogami.com/futurehttp://pyref.infogami.com/futurehttp://pyref.infogami.com/futurehttp://www.python.org/peps/pep-0343.htmlhttp://www.python.org/peps/pep-0343.htmlhttp://www.python.org/peps/pep-0343.htmlhttp://www.python.org/peps/pep-0343.htmlhttp://mail.python.org/pipermail/python-dev/2005-July/054658.htmlhttp://mail.python.org/pipermail/python-dev/2005-July/054658.htmlhttp://mail.python.org/pipermail/python-dev/2005-July/054658.htmlhttp://mail.python.org/pipermail/python-dev/2005-July/054658.htmlhttp://www.python.org/peps/pep-0343.htmlhttp://pyref.infogami.com/futurehttp://pyref.infogami.com/__future__http://pyref.infogami.com/with_statementhttp://pyref.infogami.com/__exit__http://pyref.infogami.com/__enter__http://pyref.infogami.com/__exit__http://pyref.infogami.com/continuehttp://pyref.infogami.com/breakhttp://pyref.infogami.com/returnhttp://pyref.infogami.com/__exit__http://pyref.infogami.com/Nonehttp://pyref.infogami.com/__exit__http://pyref.infogami.com/__exit__http://pyref.infogami.com/__enter__

  • 8/9/2019 Python Core Notes

    35/191

     

    Page 35of 191

    g

     

    All of the examples in the PEP and the what's new document use the with statement for things

    like locks, ensuring a socket or file is closed, database transactions and temporarily modifying a

    system setting. These are heavy duty things. Deep things. Things most people don't want to messwith. The what's new document even says

    Under the hood, the 'with' statement is fairly complicated. Most people will only use 'with' in

    company with existing objects and don't need to know these details

    I think this viewpoint is wrong, or at least overly limited. I think the PEP is more generally useful

    than those examples show and the term "context manager" is too abstract. I also conjecture that

    the people working on the PEP were systems developers and not applications developers, hence

    the bias towards system/state modification examples. ;) 

    The with Statement is very much similar to the using block in C#.

    consider an example of opening a file and making sure that it is closed after the block ends

    with open('/etc/passwd', 'r') as f:

    for line in f:

    print line

    so after the with block ends the f object is completly distroyed and the file is closed.

    and like C# the f object should implement some kind of cleanup functions to make it possible for

    the with block to call these functions automatically, in C# the object should implement

    IDisposable in python

      The expression is evaluated and should result in an object called a ``context manager''.

    The context manager must have __enter__() and __exit__() methods.

      The context manager's __enter__() method is called. The value returned is assigned to

    VAR. If no 'as VAR' clause is present, the value is simply discarded.

      The code in BLOCK is executed.

      If BLOCK raises an exception, the __exit__(type, value, traceback) is called with the

    exception details, the same values returned by sys.exc_info(). The method's return value

    controls whether the exception is re-raised: any false value re-raises the exception, and

    True will result in suppressing it. You'll only rarely want to suppress the exception,

    because if you do the author of the code containing the 'with' statement will never realize

    anything went wrong.

      If BLOCK didn't raise an exception, the __exit__() method is still called, but type, value,

    and traceback are all None.

  • 8/9/2019 Python Core Notes

    36/191

     

    Page 36of 191

    g

    the new “with” statement handles the part I care about: making it easier to write code that works

    correctly in the case of failures.

    The 3 typical use cases are a file that needs to be closed, a lock that needs to be released, and

    and a database transaction that needs to be either committed or rolled back. The database case

    is the most interesting, since you need to handle success and failure differently, and before

    version 2.5 python would not allow you to have try/except/finally. You had to pick either

    try/except or try/finally. Python 2.5 also provides a unified try/except/finally, but the “with”

    statement is easier to write, and easier to read.

    I’ve borrowed an example of what user code would look like for a database connection using the

    new “with” statement from the python docs. The idea is that the block of code should run, and

    then the transaction should either be committed or rolled back depending on whether the block

    exited normally or with an exception:

    db_connection = DatabaseConnection()

    with db_connection as cursor:

    cursor.execute('insert into ...')

    cursor.execute('delete from ...')

    # ... more operations ...

    In order for this to work, it looks like the classes that you are working with need to properly

    support a context manager which defines what should happen for success and error. But, not all

    classes will need to implement a full blown context manager, the contextlib module allows for an

    easy way to add support to existing objects without the need to write a new class.

    from contextlib import contextmanager

    @contextmanager

    def db_transaction (connection):

    http://www.python.org/dev/peps/pep-0343/http://www.python.org/dev/peps/pep-0343/http://www.python.org/dev/peps/pep-0341/http://www.python.org/dev/peps/pep-0341/http://www.python.org/dev/peps/pep-0341/http://docs.python.org/dev/whatsnew/pep-343.htmlhttp://docs.python.org/dev/whatsnew/pep-343.htmlhttp://docs.python.org/dev/whatsnew/pep-343.htmlhttp://docs.python.org/dev/whatsnew/pep-343.htmlhttp://www.python.org/dev/peps/pep-0341/http://www.python.org/dev/peps/pep-0343/

  • 8/9/2019 Python Core Notes

    37/191

     

    Page 37of 191

    g

      cursor = connection.cursor()

    try:

    yield cursor

    except:

    connection.rollback()

    raise

    else:

    connection.commit()

    db = DatabaseConnection()

    with db_transaction(db) as cursor:

    ...

    This was one area where Ruby code was much cleaner than Python, so it’s great to see the new

    functionality. It’s pretty hard for me to write code which doesn’t touch a file, a database, or

    threads, so it will be used a lot.

    Examples:

    # Public domain

    from __future__ import with_statement

    import contextlib, time

    @contextlib.contextmanager

    def accum_time(L):

  • 8/9/2019 Python Core Notes

    38/191

     

    Page 38of 191

    g

      """

    Add time used inside a with block to the value of L[0].

    """

    start = time.clock()

    try:

    yield

    finally:

    end = time.clock()

    L[0] += end - start

    # Example: measure time to execute code inside with blocks.

    t = [0]

    with accum_time(t):

    print sum(range(1000000))

    with accum_time(t):

    print sum(range(2000000))

    print 'Time:', t[0]

    another description (efBot):

    understanding the "with" statement # 

    Judging from comp.lang.python and other forums, Python 2.5's new with statement seems to be

    a bit confusing even for experienced Python programmers.

    http://online.effbot.org/2006_10_01_archive.htm#withhttp://online.effbot.org/2006_10_01_archive.htm#withhttp://online.effbot.org/2006_10_01_archive.htm#withhttp://effbot.org/pyref/with.htmhttp://effbot.org/pyref/with.htmhttp://effbot.org/pyref/with.htmhttp://effbot.org/pyref/with.htmhttp://effbot.org/pyref/with.htmhttp://online.effbot.org/2006_10_01_archive.htm#with

  • 8/9/2019 Python Core Notes

    39/191

     

    Page 39of 191

    g

    As most other things in Python, the with statement is actually very simple, once you understand

    the problem it's trying to solve. Consider this piece of code:

    set things up

    try:

    do something

    finally:

    tear things down

    Here, "set things up" could be opening a file, or acquiring some sort of external resource, and

    "tear things down" would then be closing the file, or releasing or removing the resource. The try-

    finally construct guarantees that the "tear things down" part is always executed, even if the code

    that does the work doesn't finish.

    If you do this a lot, it would be quite convenient if you could put the "set things up" and "tear

    things down" code in a library function, to make it easy to reuse. You can of course do something

    like

    def controlled_execution(callback):

    set things up

    try:

    callback(thing)

    finally:

    tear things down

    def my_function(thing):

    do something

  • 8/9/2019 Python Core Notes

    40/191

     

    Page 40of 191

    g

     

    controlled_execution(my_function)

    But that's a bit verbose, especially if you need to modify local variables. Another approach is to

    use a one-shot generator, and use the for-in statement to "wrap" the code:

    def controlled_execution():

    set things up

    try:

    yield thing

    finally:

    tear things down

    for thing in controlled_execution():

    do something with thing

    But yield isn't even allowed inside a try-finally in 2.4 and earlier. And while that could be fixed

    (and it has been fixed in 2.5), it's still a bit weird to use a loop construct when you know that you

    only want to execute something once.

    So after contemplating a number of alternatives, GvR and the python-dev team finally came up

    with a generalization of the latter, using an object instead of a generator to control the behaviour

    of an external piece of code:

    class controlled_execution:

    def __enter__(self):

    set things up

    return thing

  • 8/9/2019 Python Core Notes

    41/191

     

    Page 41of 191

    g

      def __exit__(self, type, value, traceback):

    tear things down

    with controlled_execution() as thing:

    some code

    Now, when the "with" statement is executed, Python evaluates the expression, calls the

     __enter__ method on the resulting value (which is called a "context guard"), and assigns

    whatever __enter__ returns to the variable given by as. Python will then execute the code body,

    and no matter what happens in that code , call the guard object's __exit__ method.

    As an extra bonus, the __exit__ method can look at the exception, if any, and suppress it or act

    on it as necessary. To suppress the exception, just return a true value. For example, the following

     __exit__ method swallows any TypeError, but lets all other exceptions through:

    def __exit__(self, type, value, traceback):

    return isinstance(value, TypeError)

    In Python 2.5, the file object has been equipped with __enter__ and __exit__ methods; the

    former simply returns the file object itself, and the latter closes the file:

    >>> f = open("x.txt")

    >>> f

    >>> f.__enter__()

    >>> f.read(1)

  • 8/9/2019 Python Core Notes

    42/191

     

    Page 42of 191

    g

      'X'

    >>> f.__exit__(None, None, None)

    >>> f.read(1)

    Traceback (most recent call last):

    File "", line 1, in

    ValueError: I/O operation on closed file

    so to open a file, process its contents, and make sure to close it, you can simply do:

    with open("x.txt") as f:

    data = f.read()

    do something with data

  • 8/9/2019 Python Core Notes

    43/191

     

    Page 43of 191

    g

    Functions

    A function is a group of statements that execute upon request. Python provides many built-in

    functions and allows programmers to define their own functions. A request to execute a function

    is known as a function call. When you call a function, you can pass arguments that specify dataupon which the function performs its computation. In Python, a function always returns a result

    value, either None or a value that represents the results of the computation. Functions defined

    within class statements are also known as methods. Functions are objects (values) that are

    handled like other objects. Thus, you can pass a function as an argument in a call to another

    function. Similarly, a function can return another function as the result of a call. A function, just

    like any other object, can be bound to a variable, an item in a container, or an attribute of an

    object. Functions can also be keys into a dictionary. For example, if you need to quickly find a

    function's inverse given the function, you could define a dictionary whose keys and values are

    functions and then make the dictionary bidirectional:inverse = {sin:asin, cos:acos, tan:atan, log:exp}

    for f in inverse.keys( ): inverse[inverse[f]] = f

    The def statement is the most common way to define a function. def is a single-clause

    compound statement with the following syntax:

    def function-name( parameters):

    statement(s) 

    function-name is an identifier. It is a variable that gets bound (or rebound) to the function

    object when def executes.

     parameters is an optional list of identifiers, known as formal parameters or just parameters, that

    get bound to the values supplied as arguments when the function is called. In the simplest case, a

    function doesn't have any formal parameters, which means the function doesn't take any

    arguments when it is called. In this case, the function definition has empty parentheses after

    function-name.

    When a function does take arguments, parameters

     contains one or more identifiers, separated

    by commas (,). In this case, each call to the function supplies values, known as arguments,

    corresponding to the parameters listed in the function definition. The parameters are local

    variables of the function.

  • 8/9/2019 Python Core Notes

    44/191

     

    Page 44of 191

    g

    The def statement sets some attributes of a function object. The attribute func_name, also

    accessible as _ _name_ _, refers to the identifier string given as the function name in the def 

    statement. You may rebind the attribute to any string value, but trying to unbind it raises an

    exception. The attribute func_defaults, which you may freely rebind or unbind, refers to the

    tuple of default values for the optional parameters (or the empty tuple, if the function has no

    optional parameters).

    Another function attribute is the documentation string, also known as the docstring. You may use

    or rebind a function's docstring attribute as either func_doc or _ _doc_ _. If the first statement

    in the function body is a string literal, the compiler binds that string as the function's docstring

    attribute

    In addition to its predefined attributes, a function object may have other arbitrary attributes. To

    create an attribute of a function object, bind a value to the appropriate attribute reference in an

    assignment statement after the def statement executes. For example, a function could counthow many times it gets called:

    def counter( ):

    counter.count += 1

    return counter.count counter.count = 0

    Note that this is not common usage. More often, when you want to group together some state

    (data) and some behavior (code), you should use the object-oriented mechanisms .

    The return statement is allowed only inside a function body and can optionally be followed by

    an expression. When return executes, the function terminates, and the value of the expression

    is the function's result. A function returns None if it terminates by reaching the end of its body or

    by executing a return statement that has no expression (or, of course, by executing return

    None).

    As a matter of style, you should never write a return statement without an expression at the end

    of a function body. If some return statements in a function have an expression, all return 

    statements should have an expression. return None should only be written explicitly to meet

    this style requirement. Python does not enforce these stylistic conventions.

    A function call is an expression with the following syntax:function-object(arguments)

    function-object may be any reference to a function (or other callable) object; most often, it's

    the function's name. The parentheses denote the function-call operation itself. arguments, in the

    simplest case, is a series of zero or more expressions separated by commas (,), giving values for

    the function's corresponding parameters. When the function call executes, the parameters are

  • 8/9/2019 Python Core Notes

    45/191

     

    Page 45of 191

    g

    bound to the argument values, the function body executes, and the value of the function-call

    expression is whatever the function returns.

    Note that just mentioning a function (or other callable object) does not call it. To call a function

    (or other object) without arguments, you must use ( ) after the function's name.

    In traditional terms, all argument passing in Python is by value. For example, if you pass a variable

    as an argument, Python passes to the function the object (value) to which the variable currently

    refers, not "the variable itself." Thus, a function cannot rebind the caller's variables. However, if

    you pass a mutable object as an argument, the function may request changes to that object

    because Python passes the object itself, not a copy. Rebinding a variable and mutating an object

    are totally disjoint concepts. For example:

    def f(x, y):

    x = 23

    y.append(42)

    a = 77

    b = [99]

    f(a, b)

    print a, b # prints: 77 [99, 42]

    The print statement shows that a is still bound to 77. Function f's rebinding of its parameter x 

    to23

     has no effect onf

    's caller, nor, in particular, on the binding of the caller's variable that

    happened to be used to pass 77 as the parameter's value. However, the print statement also

    shows that b is now bound to [99, 42]. b is still bound to the same list object as before the call,

    but that object has mutated, as f has appended 42 to that list object. In either case, f has not

    altered the caller's bindings, nor can f alter the number 77, since numbers are immutable.

    However, f can alter a list object, since list objects are mutable. In this example, f mutates the

    list object that the caller passes to f as the second argument by calling the object's append 

    method.

    Arguments that are just expressions are known as positional arguments. Each positional

    argument supplies the value for the parameter that corresponds to it by position (order) in thefunction definition.

    In a function call, zero or more positional arguments may be followed by zero or more named

    arguments, each with the following syntax:

    identifier =expression 

  • 8/9/2019 Python Core Notes

    46/191

     

    Page 46of 191

    g

    The identifier  must be one of the parameter names used in the def statement for the

    function. The expression supplies the value for the parameter of that name. Most built-in

    functions do not accept named arguments, you must call such functions with positional

    arguments only. However, all normal functions coded in Python accept named as well as

    positional arguments, so you may call them in different ways.

    A function call must supply, via a positional or a named argument, exactly one value for each

    mandatory parameter, and zero or one value for each optional parameter. For example:

    def divide(divisor, dividend):

    return dividend // divisor print divide(12, 94)

    # prints: 7

    print divide(dividend=94, divisor=12) # prints: 7

    As you can see, the two calls to divide are equivalent. You can pass named arguments for

    readability purposes whenever you think that identifying the role of each argument and

    controlling the order of arguments enhances your code's clarity.

    A common use of named arguments is to bind some optional parameters to specific values, while

    letting other optional parameters take default values:

    def f(middle, begin='init', end='finis'):

    return begin+middle+end print f('tini', end='') #

    prints: inittini

    Thanks to named argument end='', the caller can specify a value, the empty string '', for f's

    third parameter, end, and still let f's second parameter, begin, use its default value, the string

    'init'.

    At the end of the arguments in a function call, you may optionally use either or both of the

    special forms *seq  and **dct. If both forms are present, the form with two asterisks must be

    last. *seq  passes the items of seq  to the function as positional arguments (after the normal

    positional arguments, if any, that the call gives with the usual syntax). seq  may be any iterable.

    **dct passes the items of dct to the function as named arguments, where dct must be a

    dictionary whose keys are all strings. Each item's key is a parameter name, and the item's value is

    the argument's value.

  • 8/9/2019 Python Core Notes

    47/191

     

    Page 47of 191

    g

    Sometimes you want to pass an argument of the form *seq  or **dct when the parameters use

    similar forms. For example, using the function sum_args defined in that section (and shown again

    here), you may want to print the sum of all the values in dictionary d . This is easy with *seq :

    def sum_args(*numbers):

    return sum(numbers)

    print sum_args(*d.values( ))

    (Of course, in this case, print sum(d.values( )) would be simpler and more direct!)

    However, you may also pass arguments of the form *seq  or **dct when calling a function that

    does not use the corresponding forms in its parameters. In that case, of course, you must ensure

    that iterable seq  has the right number of items, or, respectively, that dictionary dct uses the right

    names as its keys; otherwise, the call operation raises an exception.

    A function's parameters, plus any variables that are bound (by assignment or by other binding

    statements, such as def) in the function body, make up the function's local namespace, also

    known as local scope. Each of these variables is known as a local variable of the function.

    Variables that are not local are known as global variables (in the absence of nested function

    definitions). Global variables are attributes of the module object: Whenever a function's local

    variable has the same name as a global variable, that name, within the function body, refers to

    the local variable, not the global one. We express this by saying that the local variable hides the

    global variable of the same name throughout the function body.By default, any variable that is bound within a function body is a local variable of the function. If a

    function needs to rebind some global variables, the first statement of the function must be:

    global identifiers 

    where identifiers is one or more identifiers separated by commas (,). The identifiers listed in a

    global statement refer to the global variables (i.e., attributes of the module object) that the

    function needs to rebind.

    Don't use global if the function body just uses a global variable (including mutating the object

    bound to that variable if the object is mutable). Use a global statement only if the function body

    rebinds a global variable (generally by assigning to the variable's name). As a matter of style,

    don't use global unless it's strictly necessary, as its presence will cause readers of your program

    to assume the statement is there for some useful purpose. In particular, never use global except

    as the first statement in a function body.

  • 8/9/2019 Python Core Notes

    48/191

     

    Page 48of 191

    g

    A def statement within a function body defines a nested function, and the function whose body

    includes the def is known as an outer function to the nested one. Code in a nested function's

    body may access (but not rebind) local variables of an outer function, also known as free

    variables of the nested function.

    The simplest way to let a nested function access a value is often not to rely on nested scopes, but

    rather to explicitly pass that value as one of the function's arguments. If necessary, the

    argument's value can be bound when the nested function is defined by using the value as the

    default for an optional argument. For example:

    def percent1(a, b, c):

    def pc(x, total=a+b+c): return (x*100.0) / total

    print "Percentages are:", pc(a), pc(b), pc(c)

    Here's the same functionality using nested scopes:def percent2(a, b, c):

    def pc(x): return (x*100.0) / (a+b+c)

    print "Percentages are:", pc(a), pc(b), pc(c)

    In this specific case, percent1 has a tiny advantage: the computation of a+b+c happens only

    once, while percent2's inner function pc repeats the computation three times. However, if the

    outer function rebinds its local variables between calls to the nested function, repeating the

    computation can be necessary. It's therefore advisable to be aware of both approaches, and

    choose the most appropriate one case by case.

    A nested function that accesses values from outer local variables is also known as a closure. The

    following example shows how to build a closure:

    def make_adder(augend):

    def add(addend):

    return addend+augend

    return add

    Closures are an exception to the general rule that the object-oriented mechanisms are the best

    way to bundle together data and code. When you need specifically to construct callable objects,

    with some parameters fixed at object construction time, closures can be simpler and more

    effective than classes. For example, the result of make_adder(7) is a function that accepts a

    single argument and adds 7 to that argument. An outer function that returns a closure is a

    "factory" for members of a family of functions distinguished by some parameters, such as the

  • 8/9/2019 Python Core Notes

    49/191

     

    Page 49of 191

    g

    value of argument augend  in the previous example, and may often help you avoid code

    duplication.

  • 8/9/2019 Python Core Notes

    50/191

     

    Page 50of 191

    g

    Classes

    A class is a Python object with several characteristics:

      You can call a class object as if it were a function. The call returns another object, known

    as an instance of the class; the class is also known as the type of the instance.

      A class has arbitrarily named attributes that you can bind and reference.

      The values of class attributes can be descriptors (including functions or normal data

    objects.

      Class attributes bound to functions are also known as methods of the class.

      A method can have a special Python-defined name with two leading and two trailing

    underscores. Python implicitly invokes such special methods, if a class supplies them,

    when various kinds of operations take place on instances of that class.  A class can inherit from other classes, meaning it delegates to other class objects the

    lookup of attributes that are not found in the class itself.

    An instance of a class is a Python object with arbitrarily named attributes that you can bind and

    reference. An instance object implicitly delegates to its class the lookup of attributes not found in

    the instance itself. The class, in turn, may delegate the lookup to the classes from which it

    inherits, if any.

    In Python, classes are objects (values) and are handled like other objects. Thus, you can pass a

    class as an argument in a call to a function. Similarly, a function can return a class as the result of

    a call. A class, just like any other object, can be bound to a variable (local or global), an item in a

    container, or an attribute of an object. Classes can also be keys into a dictionary. The fact that

    classes are ordinary objects in Python is often expressed by saying that classes are first-class

    objects.

    A descriptor is any new-style object whose class supplies a special method named _ _get_ _.

    Descriptors that are class attributes control the semantics of accessing and setting attributes on

    instances of that class. Roughly speaking, when you access an instance attribute, Python obtains

    the attribute's value by calling _ _get_ _ on the corresponding descriptor, if any.

    If a descriptor's class also supplies a special method named _ _set_ _, then the descriptor is

    known as an overriding descriptor (or, by an older and slightly confusing terminology, a data

    descriptor); if the descriptor's class supplies only _ _get_ _, and not _ _set_ _, then the

    descriptor is known as a nonoverriding (or nondata) descriptor. For example, the class of function

  • 8/9/2019 Python Core Notes

    51/191

     

    Page 51of 191

    g

    objects supplies _ _get_ _, but not _ _set_ _; therefore, function objects are nonoverriding

    descriptors. Roughly speaking, when you assign a value to an instance attribute with a

    corresponding descriptor that is overriding, Python sets the attribute value by calling _ _set_ _ 

    on the descriptor.

    A common task is to create instances of different classes depending on some condition, or to

    avoid creating a new instance if an existing one is available for reuse. A common misconception is

    that such needs might be met by having _ _init_ _ return a particular object, but such an

    approach is absolutely unfeasible: Python raises an exception when _ _init_ _ returns any

    value other than None. The best way to implement flexible object creation is by using an ordinary

    function rather than calling the class object directly. A function used in this role is known as a

    factory function.

    Calling a factory function is a flexible approach: a function may return an existing reusable

    instance, or create a new instance by calling whatever class is appropriate. Say you have two

    almost interchangeable classes (SpecialCase and NormalCase) and want to flexibly generate

    instances of either one of them, depending on an argument. The following appropriateCase 

    factory function allows you to do just that

    class SpecialCase(object):

    def amethod(self): print "special"

    class NormalCase(object):

    def amethod(self): print "normal"

    def appropriateCase(isnormal=True):

    if isnormal: return NormalCase( )

    else: return SpecialCase( )

    aninstance = appropriateCase(isnormal=False)

    aninstance.amethod( ) # prints "special", as desired

    The built-in object type is the ancestor of all built-in types and new-style classes. The object 

    type defines some special methods that implement the default semantics of objects:

     _ _new_ _ _ _init_ _

  • 8/9/2019 Python Core Notes

    52/191

  • 8/9/2019 Python Core Notes

    53/191

     

    Page 53of 191

    g

    A property is an instance attribute with special functionality. You reference, bind, or unbind the

    attribute with the normal syntax (e.g.,