|
Python programming language
|
basic syntaxstmt: # trailing colon introduces stmt2 # an indented statement or clause # # comment \ # line continuation ; # statement separator (like C) if cash > price: Eggs(); Spam() # we eat both if we've enuff money True False # note spelling (Python 2.3) "abc" # strings can be enclosed 'abc' # in single or double quotes s = 'abc' s[0] = 'A' # wrong: strings are immutable (n,n,...) # tuple n,n,... # tuple t = (1, 2, 3) # named tuple variable n = t[0] # access tuple element t = ('math',101) # create named tuple (course,num) = t # unpack tuple [n,n,...] # list list = [ 'a', 'b', 'c' ] # list variable list[1] # access element list = [ 'eggs', 12 ] # heterogenous lists are supported by Python # but using tuples as elements may be better d = {'vorlon':0, 'shadow':1} # create dictionary d['vorlon'] # access by key None # NULL not # logical/boolean not returns True/False # Logical/boolean and/or # For 'X or Y', returns X if it's true, else Y # For 'X and Y', returns X if it's false, else Y # Both return an object, not true/false nor 0/1! a = 0; b = 2; plan = a or b # plan = 2 (not 1 as one might expect) i = 0; L = []; z = i or L # z = [] (z = L) i = 0; L = []; z = L or i # z = 0 (z = i) & | ~ # bitwise == != < > <= >= # equality, relational is # object identity is not ** # power (x^y) // # floor division (truncates to integer) pass # NOP * # multiple meanings: str = 2 * 'abc' # repeats a string: 'abcabc' x = (1, 2, 3) # unpacks a tuple into individual values func( *x ) # pass 3 separate args rather than a tuple += -= *= etc # shorthand like C if <cond>: # conditional [elif <cond>:] [else:] while <cond>: # while loop [break] # break out of looping [continue] # iterate to top of loop [else:] # 'else' clause will execute when condition becomes false. # To be exact, 'else' will execute unless 'break' was executed. for item in sequence: if item == sought: break else: # This is Pythonic way of saying "if item not found". print item, 'not found' # 'else' clause will execute unless 'break' was executed. return # implicitly returns None return (res1,res2) # a tuple can be used to return multiple values try: # except clause executed if exception matches [except [exception[,value]]]: # omitted name matches any exception else: # else clause executed if no exception def func( arg1, arg2 = 10 ) # second arg has a default def func( *arg ) # arg is a tuple (arbitrary number of arguments) func( (123, 456, 789) ) # arg = ( 123, 456, 789 ) foo( name='eggs', age='12' ) # args can be specified by name def func( arg1, **arg2 ) # final arg is a dictionary float(123) float('123.0') # convert integer/string to float str(123) # convert to string (stringify) `123` # convert to string (stringify) (deprecated) int(1.5) # convert to integer (truncate) bool(x) # convert to boolean hex(15) # convert to string in hex format int('101',2) # convert to int from binary number in string # A list comprehension is a shorthand with two usual forms: # [ x for x in seq ] # [ x for x in seq if expr ] # A list comprehension creates a new list by appending 'x' # on every iteration of 'for x in seq'. # If an optional 'if' clause is written, 'x' is only appended # if 'if' clause evaluates to true. list = [ 1, 2, 3, 4, 5, 6 ] result = [ 2*x for x in list] # new list whose elements are double result = [ x for x in list if x % 2 == 0 ] # new list with even values # lamba creates an anonymous function. Unlike 'def', # formal args aren't parenthesized. A lambda is limited to # being an expression and its result is implicitly returned. sum = lambda a, b: a + b x = sum(10,20) # Class attributes have similarities to C++ static members. # Inside a class block, they're set using their unqualified names. # But inside a method, class attributes require class-qualified names # to distinguish them from method local vars and instance attributes. class Class: msCnt = 0 # right Class.msCnt = 0 # wrong (class name isn't valid yet) def __init__( self ): print msCnt # wrong (non-existent local var) print s.msCnt # technically wrong (will work): class attribute confused as instance attribute print Class.msCnt # right self.msCnt += 1 # wrong: changes this instance's attribute, not class attribute Class.msCnt += 1 # right |
common phrases, expressions, idiomsperson = 'Methuselah' # counterpart to C printf() age = 969 print '%s lived %d years.' % (person, age) if 90 <= percent <= 100: # between test x or y # result is x if x is True or y x and y # result is y if x is True or x return x or y or None # return x if it's True, or y if it's True, or None a, b = b, a # swap a, b = 0, 2 # Since boolean 'or' returns first object that is true, plan = a or b # it can be written as a terse idiom instead of if/else. if a: # Result is plan = 2 (not plan = 1) plan = a else: plan = b t = () # empty tuple t = 'a', # trailing comma necessary to assign tuple t = ('abc',1) # to modify a tuple: t[1] = 2 # wrong t = (t[0],2) # right (by reassignment) tup = (64, 'bits') # comparing objects of utterly different types is allowed if tup[0] == tup[1]: # which may be useful with heterogenous sequences list = [] # to append to a list: list[0] = 'a' # wrong, would throw IndexError list.append( 'a' ) # right list = [None] * 256 # pre-allocate 256 elements (None repeated 256 times) list[255] = 1 # ok list[:] # select entire sequence str[:] # don't write list[0:-1] (pitfalls) for i in xrange(10): print i # iterate thru {0,..,9} # avoid range() which has a pitfall for element in [1, 3, 7, 12]: # iterate thru a LIST for element in (1, 3, 7, 12): # iterate thru a TUPLE for line in open('myfile.txt'): # print lines of a file print line x in seq, x not in seq # True/False if x is/not in sequence word = 'abc' + 'def' # catenate strings # Positive indexes are zero-based. # Negative indexes are allowed. data[0] # first elem data[-1] # last elem # Slicing applies to a sequence (strings, lists). # Lower bound is inclusive, upper bound is exclusive. data[:2] # first two elems data[2:] # all elems following first two data[-2:] # last two elems data[:-2] # all elems excluding last two data[::-1] # reverses order (Python 2.3) del list[i] # delete ith element aString = 'abc' # to unpack: aList = [1, 2, 3] aTuple = 'Jane', 28, 'CS' first, second, third = aString # unpack string first, second, third = aList # unpack list first, second, third = aTuple # unpack tuple class Object: # declaring a class def foo( self ): # self is always first arg of class methods obj.data # accessing a class member class Derived(Object) # deriving a class class Derived2(Base1,Base2) # multiple inheritance class Object: # __init__() is always name def __init__(self): # of every constructor in Python obj = Object() # instantiating an object from a class class Object: # Class members can be created by constructor. def __init__(self): # .data is created dynamically in this case. self.data = GetData() # Note that 'self.' is necessary. class Base: # Programmer must explicitly call def __init__(self): # base constructors in Python. ... class Derived: def __init__(self): Base.__init__(self) class MyClass: # Python nearest counterpart to C++'s private def __init__(self): # is to prepend two underscores to a member. self.__private = 1 # iter*() returns iterators. Pitfall: Loop must not modify dictionary. for k in d.iterkeys(): # iterate thru keys in dictionary (by iterator object) for v in d.itervalues(): # iterate thru values in dictionary (by iterator object) for (k,v) in d.iteritems(): # iterate thru pairs in dictionary (by iterator object) # values(),keys(),items() return lists derived from dictionary. for k in d.keys(): # iterate thru list of keys from dictionary if k == deleted: del d[k] # ok: iteration is thru list rather than dictionary for v in d.values(): # iterate thru list of values from dictionary for (k,v) in d.items(): # iterate thru list of pairs from dictionary i = 123 # test type of an object if isinstance(i,int): >>> type(i) <type 'int'> def Func(): # This isn't a dangling reference. x = 123 # name 'x' is destroyed when function returns return x # but object referenced by 'x' is returned. y = Func() |
pitfalls, traps, quirks# Pitfall: A silent NOP! ++ is two unary positive operators in Python! ++x # Pitfall: Use xrange() instead of range(). # Same syntax. xrange() creates an iterator. range() creates a list. for i in range(10*1024*1024): # wrong: that's why you ran out of swap-space # Pitfall: Trying to modify a function arg by assignment # is wrong because a function arg is a local name. Mangle(list) # wrong: this won't be an in-place modification def Mangle(list): list = list[1:] # wrong: creates a new list and assigns to a local name list = Mangle(list) # right def Mangle(list): list = list[1:] return list list = Mangle(list) # better def Mangle(list): del list[0] return list # Pitfall: Modifying a sequence by a loop: list = [ 0, 0, 0 ] for item in list: # wrong: changes item not list[] item = 1 # item is a temporary object for i in xrange( len(list) ): list[i] = 1 # right # Pitfall: Tuple elements cannot be re-assigned. # But a tuple as a whole can be. t = (1, 2) t[1] = 3 # wrong t = (t[0], 3) # right # Pitfall: For basic types, assignment effectively creates a copy. # But for all other objects, assignment creates a reference!! # Assignment to basic type: x = 1 y = x x = 2 # results: x = 2, y = 1 (as you would expect) # Assignment to non-basic type: list = [ 1, 2 ] listSaved = list list[0] = 3 # wrong: list[0] = listSaved[0] = 3 listSaved = list[:] # right (shallow copy) # Pitfall: shallow copy vs. deep copy. # A shallow copy of a list only copies # first-level elements. # If a list contains nested lists, # a deep copy is necessary to make copies # of nested lists. listSaved = list[:] # shallow copy import copy listSaved = copy.deepcopy(list) # deep copy # Pitfall: deleting a list element. list = [ 1, 2, 3 ] list[0] = [] # wrong, turns list[0] into empty list: [ [], 2, 3 ] del list[0] # right # Pitfall: del removes elements from a list but # doesn't really delete elements themselves. obj1 = MyClass() obj2 = MyClass() list = [ obj1, obj2 ] del list[:] # list emptied but obj1, obj2 survive # Pitfall: To avoid slice pitfalls: # Remember that lower bound is inclusive but upper is exclusive. # Think of indices as pointing between characters, # with left edge of first character numbered 0. # Right edge of element n is at index n (upper bound). # # +---+---+---+---+---+ # | A | B | C | D | E | # +---+---+---+---+---+ # 0 1 2 3 4 5 # -5 -4 -3 -2 -1 # # For example: # s = 'ABCDE' # s[0:4] is 'ABCD' (not 'ABCDE') # s[-5:-1] is 'ABCD' also (s[-1:-5] would be wrong) # Pitfall: Intent is to remove all elements from a list: del list[0:-1] # wrong, removes all elements except last del list[:] # right # Pitfall: invoking base constructors. # Python doesn't call __init__() methods of base (ancestor) classes. # Programmer must explicitly call ancestor __init__() methods # or call super(). # Pitfall: Use 'global' to assign a global variable # by a function (similar to PHP) to avoid UnboundLocalError. gx = 0 def Func(x): global gx gx = gx + x return def Func2(): gx = 1 # wrong: creates gx in local scope (need global gx) # Pitfall: Built-in names can be reassigned by mistake. open = True # wrong |
tricks, recipesTrick: Portable way to locate python interpreter #!/usr/bin/env python Trick: Abbreviating self # Writing 'self' is only a convention: it can be written as 's' for brevity. class Class: def __init__( s ): Trick: static local variable # Functions can be given attributes which can serve as static local variables. def func( input ): if input == func.lastInput: # avoid recomputing same input return func.lastResult func.lastInput = None func.lastResult = None Trick: Counterpart to C++ static class member # Python class attributes can be used (with care) # as counterparts to C++ static class members. # By contrast, data attributes are per-instance variables. # A class attribute must be assigned using name of class. # Assigning a class attribute using name of an instance is a pitfall # as it will create a per-instance variable that'll override class variable. class MyClass: shared = 1 c1 = MyClass() c2 = MyClass() c1.shared = 2 # wrong: affects only c1 (c2.shared is still 1) MyClass.shared = 2 # right: affects all instances of MyClass # (except those with an overriding per-instance variable) Trick: Constant (read-only) variables # By Alex Martelli http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207 # Put in const.py...: class _const: class ConstError(TypeError): pass def __setattr__(self,name,value): if self.__dict__.has_key(name): raise self.ConstError, 'Can not rebind const(%s)' % name self.__dict__[name] = value import sys sys.modules[__name__] = _const() # that's all -- now any client-code can import const # and bind an attribute ONCE: const.magic = 23 # but NOT re-bind it: const.magic = 88 # raises const.ConstError # you may also want to add obvious __delattr__ |
code snippets# Dynamically create a list of lists (multi-dimensional list). # This snippet is from pyspaceinvaders: it has a list of # alien columns in which each column is a list of alien objects. alienColCnt = 10 alienColumns = [] for col in range(alienColCnt): alienColumns.append( [] ) # add list as an element (nested list) alien = Alien() # new Alien object alienColumns[col].append( alien ) # add to 2nd-level list # Prune invalid objects in a list. # Requires: Objects in elements have a .valid member. # List is flat (no nested sequences). # Deleting items while iterating thru a list # is an error in Python, so a copy is used. def PruneList( list ): tmp = list[:] # copy list (shallow copy) i = -1 for obj in tmp: i += 1 if not obj.valid: del list[i] i -= 1 return # Prune invalid objects in a list of lists (2D list). # Requires: Objects in elements have a .valid member. # List must not be deeper than 2 levels. def PruneListList( listList ): tmpListList = listList[:] # copy list (shallow copy) i = -1 for list2 in tmpListList: # for each 2nd-level list i += 1 j = -1 for obj in list2: j += 1 if not obj.valid: del listList[i][j] j -= 1 return # Iterate over a list of tuples. tupleList = [ ('math',101), ('chemistry',102) ] for t in tupleList: print 'class %s %d' % t for (course,num) in tupleList: # alternative print 'class %s %d' % (course,num) # ------------------------------------ # Printing a user-defined class/object # ------------------------------------ class MyClass: def __init__(self,n): self.val = n def __str__(self): return 'val = %d' % self.val obj = MyClass(12) print obj # Remove duplicates from a list. def Unique( l ): d = {} for k in l: d[k] = 1 return d.keys() |
commentary/opinionpositive opinionPython code is very sleek and readable by indentation. Python offers many libraries. negative opinionThis author switched from Python to Lua after Python 3 broke compatibility with existing Python 2 programs by so-called "enhancements" that seemed whimsical or pedantic. |