#----------------------------- # DO NOT DO THIS... greeted = 0 def hello(): global greeted greeted += 1 print "hi there" #... as using a callable object to save state is cleaner # class hello # def __init__(self): # self.greeted = 0 # def __call__(self): # self.greeted += 1 # print "hi there" # hello = hello() #----------------------------- hello() # call subroutine hello with no arguments/parameters #----------------------------- |
#----------------------------- import math # Provided for demonstration purposes only. Use math.hypot() instead. def hypotenuse(side1, side2): return math.sqrt(side1**2 + side2**2) diag = hypotenuse(3, 4) # diag is 5.0 #----------------------------- print hypotenuse(3, 4) # prints 5.0 a = (3, 4) print hypotenuse(*a) # prints 5.0 #----------------------------- both = men + women #----------------------------- nums = [1.4, 3.5, 6.7] # Provided for demonstration purposes only. Use: # ints = [int(num) for num in nums] def int_all(nums): retlist = [] # make new list for return for n in nums: retlist.append(int(n)) return retlist ints = int_all(nums) # nums unchanged #----------------------------- nums = [1.4, 3.5, 6.7] def trunc_em(nums): for i,elem in enumerate(nums): nums[i] = int(elem) trunc_em(nums) # nums now [1,3,6] #----------------------------- # By convention, if a method (or function) modifies an object # in-place, it returns None rather than the modified object. # None of Python's built-in functions modify in-place; methods # such as list.sort() are somewhat more common. mylist = [3,2,1] mylist = mylist.sort() # incorrect - returns None mylist = sorted(mylist) # correct - returns sorted copy mylist.sort() # correct - sorts in-place #----------------------------- |
#----------------------------- # Using global variables is discouraged - by default variables # are visible only at and below the scope at which they are declared. # Global variables modified by a function or method must be declared # using the "global" keyword if they are modified def somefunc(): variable = something # variable is invisible outside of somefunc #----------------------------- import sys name, age = sys.args[1:] # assumes two and only two command line parameters start = fetch_time() #----------------------------- a, b = pair c = fetch_time() def check_x(x): y = "whatever" run_check() if condition: print "got", x #----------------------------- def save_list(*args): Global_List.extend(args) #----------------------------- |
#----------------------------- ## Python allows static nesting of scopes for reading but not writing, ## preferring to use objects. The closest equivalent to: #{ # my $counter; # sub next_counter { return ++$counter } #} ## is: def next_counter(counter=[0]): # default lists are created once only. counter[0] += 1 return counter[0] # As that's a little tricksy (and can't make more than one counter), # many Pythonistas would prefer either: def make_counter(): counter = 0 while True: counter += 1 yield counter next_counter = make_counter().next # Or: class Counter: def __init__(self): self.counter = 0 def __call__(self): self.counter += 1 return self.counter next_counter = Counter() #----------------------------- ## A close equivalent of #BEGIN { # my $counter = 42; # sub next_counter { return ++$counter } # sub prev_counter { return --$counter } #} ## is to use a list (to save the counter) and closured functions: def make_counter(start=0): counter = [start] def next_counter(): counter[0] += 1 return counter[0] def prev_counter(): counter[0] -= 1 return counter[0] return next_counter, prev_counter next_counter, prev_counter = make_counter() ## A clearer way uses a class: class Counter: def __init__(self, start=0): self.value = start def next(self): self.value += 1 return self.value def prev(self): self.value -= 1 return self.value def __int__(self): return self.value counter = Counter(42) next_counter = counter.next prev_counter = counter.prev #----------------------------- |
## This sort of code inspection is liable to change as ## Python evolves. There may be cleaner ways to do this. ## This also may not work for code called from functions ## written in C. #----------------------------- import sys this_function = sys._getframe(0).f_code.co_name #----------------------------- i = 0 # how far up the call stack to look module = sys._getframe(i).f_globals["__name__"] filename = sys._getframe(i).f_code.co_filename line = sys._getframe(i).f_lineno subr = sys._getframe(i).f_code.co_name has_args = bool(sys._getframe(i+1).f_code.co_argcount) # 'wantarray' is Perl specific #----------------------------- me = whoami() him = whowasi() def whoami(): sys._getframe(1).f_code.co_name def whowasi(): sys._getframe(2).f_code.co_name #----------------------------- |
#----------------------------- # Every variable name is a reference to an object, thus nothing special # needs to be done to pass a list or a dict as a parameter. list_diff(list1, list2) #----------------------------- # Note: if one parameter to zip() is longer it will be truncated def add_vecpair(x, y): return [x1+y1 for x1, y1 in zip(x, y)] a = [1, 2] b = [5, 8] print " ".join([str(n) for n in add_vecpair(a, b)]) #=> 6 10 #----------------------------- # DO NOT DO THIS: assert isinstance(x, type([])) and isinstance(y, type([])), \ "usage: add_vecpair(list1, list2)" #----------------------------- |
#----------------------------- # perl return context is not something standard in python... # but still you can achieve something alike if you really need it # (but you must really need it badly since you should never use this!!) # # see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 for more # # NB: it has been tested under Python 2.3.x and no guarantees can be given # that it works under any future Python version. import inspect,dis def expecting(): """Return how many values the caller is expecting""" f = inspect.currentframe().f_back.f_back bytecode = f.f_code.co_code i = f.f_lasti instruction = ord(bytecode[i+3]) if instruction == dis.opmap['UNPACK_SEQUENCE']: howmany = ord(bytecode[i+4]) return howmany elif instruction == dis.opmap['POP_TOP']: return 0 return 1 def cleverfunc(): howmany = expecting() if howmany == 0: print "return value discarded" if howmany == 2: return 1,2 elif howmany == 3: return 1,2,3 return 1 cleverfunc() x = cleverfunc() print x x,y = cleverfunc() print x,y x,y,z = cleverfunc() print x,y,z |
#----------------------------- thefunc(increment= "20s", start="+5m", finish="+30m") thefunc(start= "+5m",finish="+30m") thefunc(finish= "+30m") thefunc(start="+5m", increment="15s") #----------------------------- def thefunc(increment='10s', finish='0', start='0'): if increment.endswith("m"): pass #----------------------------- |
#----------------------------- a, _, c = func() # Use _ as a placeholder... a, ignore, c = func() # ...or assign to an otherwise unused variable #----------------------------- |
#----------------------------- def somefunc(): mylist = [] mydict = {} # ... return mylist, mydict mylist, mydict = somefunc() #----------------------------- def fn(): return a, b, c #----------------------------- h0, h1, h2 = fn() tuple_of_dicts = fn() # eg: tuple_of_dicts[2]["keystring"] r0, r1, r2 = fn() # eg: r2["keystring"] #----------------------------- |
#----------------------------- # Note: Exceptions are almost always preferred to error values return #----------------------------- def empty_retval(): return None def empty_retval(): return # identical to return None def empty_retval(): pass # None returned by default (empty func needs pass) #----------------------------- a = yourfunc() if a: pass #----------------------------- a = sfunc() if not a: raise AssertionError("sfunc failed") assert sfunc(), "sfunc failed" #----------------------------- |
# Prototypes are inapplicable to Python as Python disallows calling # functions without using brackets, and user functions are able to # mimic built-in functions with no special actions required as they # only flatten lists (and convert dicts to named arguments) if # explicitly told to do so. Python functions use named parameters # rather than shifting arguments: def myfunc(a, b, c=4): print a, b, c mylist = [1,2] mydict1 = {"b": 2, "c": 3} mydict2 = {"b": 2} myfunc(1,2,3) #=> 1 2 3 myfunc(1,2) #=> 1 2 4 myfunc(*mylist) #=> 1 2 4 myfunc(5, *mylist) #=> 5, 1, 2 myfunc(5, **mydict1) #=> 5, 2, 3 myfunc(5, **mydict2) #=> 5, 2, 4 myfunc(c=3, b=2, a=1) #=> 1, 2, 3 myfunc(b=2, a=1) #=> 1, 2, 4 myfunc(mylist, mydict1) #=> [1, 2] {'c': 3, 'b': 2} 4 # For demonstration purposes only - don't do this def mypush(mylist, *vals): mylist.extend(vals) mylist = [] mypush(mylist, 1, 2, 3, 4, 5) print mylist #=> [1, 2, 3, 4, 5] |
#----------------------------- raise ValueError("some message") # specific exception class raise Exception("use me rarely") # general exception raise "don't use me" # string exception (deprecated) #----------------------------- # Note that bare excepts are considered bad style. Normally you should # trap specific exceptions. For instance these bare excepts will # catch KeyboardInterrupt, SystemExit, and MemoryError as well as # more common errors. In addition they force you to import sys to # get the error message. import warnings, sys try: func() except: warnings.warn("func raised an exception: " + str(sys.exc_info()[1])) #----------------------------- try: func() except: warnings.warn("func blew up: " + str(sys.exc_info()[1])) #----------------------------- class MoonPhaseError(Exception): def __init__(self, phase): self.phase = phase class FullMoonError(MoonPhaseError): def __init__(self): MoonPhaseError.__init__("full moon") def func(): raise FullMoonError() # Ignore only FullMoonError exceptions try: func() except FullMoonError: pass #----------------------------- # Ignore only MoonPhaseError for a full moon try: func() except MoonPhaseError, err: if err.phase != "full moon": raise #----------------------------- |
# There is no direct equivalent to 'local' in Python, and # it's impossible to write your own. But then again, even in # Perl it's considered poor style. # DON'T DO THIS (You probably shouldn't use global variables anyway): class Local(object): def __init__(self, globalname, val): self.globalname = globalname self.globalval = globals()[globalname] globals()[globalname] = val def __del__(self): globals()[self.globalname] = self.globalval foo = 4 def blah(): print foo def blech(): temp = Local("foo", 6) blah() blah() blech() blah() #----------------------------- |
#----------------------------- grow = expand grow() # calls expand() #----------------------------- one.var = two.table # make one.var the same as two.table one.big = two.small # make one.big the same as two.small #----------------------------- fred = barney # alias fred to barney #----------------------------- s = red("careful here") print s #> <FONT COLOR='red'>careful here</FONT> #----------------------------- # Note: the 'text' should be HTML escaped if it can contain # any of the characters '<', '>' or '&' def red(text): return "<FONT COLOR='red'>" + text + "</FONT>" #----------------------------- def color_font(color, text): return "<FONT COLOR='%s'>%s</FONT>" % (color, text) def red(text): return color_font("red", text) def green(text): return color_font("green", text) def blue(text): return color_font("blue", text) def purple(text): return color_font("purple", text) # etc #----------------------------- # This is done in Python by making an object, instead of # saving state in a local anonymous context. class ColorFont: def __init__(self, color): self.color = color def __call__(self, text): return "<FONT COLOR='%s'>%s</FONT>" % (self.color, text) colors = "red blue green yellow orange purple violet".split(" ") for name in colors: globals()[name] = ColorFont(name) #----------------------------- # If you really don't want to make a new class, you can # fake it somewhat by passing in default args. colors = "red blue green yellow orange purple violet".split(" ") for name in colors: def temp(text, color = name): return "<FONT COLOR='%s'>%s</FONT>" % (color, text) globals()[name] = temp #----------------------------- |
# Python has the ability to derive from ModuleType and add # new __getattr__ and __setattr__ methods. I don't know the # expected way to use them to emulate Perl's AUTOLOAD. Instead, # here's how something similar would be done in Python. This # uses the ColorFont defined above. #----------------------------- class AnyColor: def __getattr__(self, name): return ColorFont(name) colors = AnyColor() print colors.chartreuse("stuff") #----------------------------- ## Skipping this translation because 'local' is too Perl ## specific, and there isn't enough context to figure out ## what this is supposed to do. #{ # local *yellow = \&violet; # local (*red, *green) = (\&green, \&red); # print_stuff(); #} #----------------------------- |
#----------------------------- def outer(arg1): x = arg1 + 35 def inner(): return x * 19 return x + inner() #----------------------------- |
#----------------------------- import mailbox, sys mbox = mailbox.PortableUnixMailbox(sys.stdin) def extract_data(msg, idx): subject = msg.getheader("Subject", "").strip() if subject[:3].lower() == "re:": subject = subject[3:].lstrip() text = msg.fp.read() return subject, idx, msg, text messages = [extract_data(idx, msg) for idx, msg in enumerate(mbox)] #----------------------------- # Sorts by subject then by original position in the list for subject, pos, msg, text in sorted(messages): print "%s\n%s"%(msg, text) #----------------------------- # Sorts by subject then date then original position def subject_date_position(elem): return (elem[0], elem[2].getdate("Date"), elem[1]) messages.sort(key=subject_date_position) # Pre 2.4: messages = sorted(messages, key=subject_date_position) #----------------------------- |