Dies ist die Support Website des Buches:
Das Python Praxisbuch
Der große Profi-Leitfaden für Programmierer
Farid Hajji
Addison Wesley / Pearson Education
ISBN 978-3-8273-2543-3 (Sep 2008), 1298 Seiten.
8. Funktionen¶
Funktionen aufrufen¶
Die Funktion foo
:
def foo(p1, p2):
"Transmogrify p1 and p2 into a string."
return p1[::-1] + p2
Die Funktion foobar
:
def foobar(p1, p2="world"):
"Transmogrify p1 and p2 into a string."
return p1[::-1] + p2
Funktionsparameter¶
Die Funktion foo
:
def foo(p1, p2=42, *p, **kw):
"Print positional parameters, *p and **kw forms"
print "p1 =", p1
print "p2 =", p2
print "*p =", p
print "**kw =", kw
Die Funktion summer
:
def summer(*p):
"Sum all numbers"
result = 0
for num in p:
result = result + num
return result
Die Funktion foobar
:
def foobar(p1, store={}):
"Function with meta data"
if isinstance(store, dict):
store['counter'] = store.get('counter', 0) + 1
print "foobar called", store['counter'], "time(s)"
else:
print "store(shadowed) =", store
# Do something with p1
print "p1 =", p1
Die Funktion foobar2
:
def foobar2(p1, store={}):
"Function with meta data"
if isinstance(store, dict):
the_counter = store.get('counter', 0)
if isinstance(the_counter, int):
store['counter'] = the_counter + 1
print "foobar2 called", store['counter'], "time(s)"
else:
# store['counter'] wasn't a counter!
print "store =", store
else:
print "store(shadowed) =", store
# Do something with p1:
print "p1 =", p1
Rückgabewerte¶
Die Funktionen foo1
und foo2
:
def foo1():
"Return multiple values in a list"
return ['john doe', '555-2323', 'jdoe@example.com']
def foo2():
"Return multiple values in a dictionary"
return {'name': 'john doe', 'phone': '555-2323',
'email': 'jdoe@example.com'}
Scope¶
Die Funktion set_a
:
def set_a(value):
"Set a to value"
a = value
print "New value:", a
Die Funktion set_b
:
def set_b(value):
"Set global b to value"
global b
b = value
print "New value:", b
Lokale und globale Namensräume verstehen¶
Die Funktion show_namespaces
:
import pprint
def show_namespaces():
"Display local and global namespaces"
foo = 'a local variable'
bar = 99999
print "locals() =="
pprint.pprint(locals())
print "globals() =="
pprint.pprint(globals())
Die Funktion factorial
:
def factorial(n):
"Returns n!"
result = n
if result > 1:
result = result * factorial(n-1)
print "locals() of factorial(%d) ==" % n, locals()
return result
Ein Blick unter die Haube¶
Die Funktion f
:
def f(p1, p2='hi', *alist, **adict):
"A function that prints its arguments"
print "p1:", p1
print "p2:", p2
print "*alist:", alist
print "**adict:", adict
return [ p1, p2 ]
Disassembliert sieht es so aus:
>>> inspect.dis.disassemble(fc)
3 0 LOAD_CONST 1 ('p1:')
3 PRINT_ITEM
4 LOAD_FAST 0 (p1)
7 PRINT_ITEM
8 PRINT_NEWLINE
4 9 LOAD_CONST 2 ('p2:')
12 PRINT_ITEM
13 LOAD_FAST 1 (p2)
16 PRINT_ITEM
17 PRINT_NEWLINE
5 18 LOAD_CONST 3 ('*alist:')
21 PRINT_ITEM
22 LOAD_FAST 2 (alist)
25 PRINT_ITEM
26 PRINT_NEWLINE
6 27 LOAD_CONST 4 ('**adict:')
30 PRINT_ITEM
31 LOAD_FAST 3 (adict)
34 PRINT_ITEM
35 PRINT_NEWLINE
7 36 LOAD_FAST 0 (p1)
39 LOAD_FAST 1 (p2)
42 BUILD_LIST 2
45 RETURN_VALUE
Die Funktion g
:
def g(a, b):
"Add two numbers, and return the result"
res = a + b
return res
sieht disassembliert so aus:
>>> inspect.dis.disassemble(g.func_code)
3 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_ADD
7 STORE_FAST 2 (res)
4 10 LOAD_FAST 2 (res)
13 RETURN_VALUE
Screenshots:
Factory-Funktionen und -Closures¶
Die Funktion create_prompter
:
def create_prompter(prompt):
"A factory that creates prompting functions"
def prompter():
"Ask the user a question and return reply as string"
return raw_input(prompt + " ")
return prompter
Dekoratoren¶
Dekoratoren manuell erstellen¶
Die Funktion foo
:
def foo():
"A very simple function"
print "I am foo()"
Die Funktion tracefoo
:
def tracefoo():
"Trace each call to foo"
print "TRACE: foo"
return foo()
Die Factory-Funktion tracer_function
:
def tracer_function(f):
"Create a tracer for function f"
def tracer():
"A tracer for f"
print "TRACE:", f.func_name
return f()
return tracer
Die Funktion bar
mit Dekorator tracer_function
:
@tracer_function
def bar():
"Another very simple function"
print "I am bar()"
Die Funktion doubler
:
def doubler(num):
"Returns the double of a number num"
return num + num
Die Funktion tracer_function_1arg
:
def tracer_function_1arg(f):
"Create a tracer for function f, where f takes one argument"
def tracer(thearg):
"A tracer for f"
print "TRACE:", f.func_name
return f(thearg)
return tracer
Die Funktion tracer_function_general
:
def tracer_function_general(f):
"Create a tracer for function f, f takes *p and **kw forms"
def tracer(*p, **kw):
"A tracer for f"
print "TRACE:", f.func_name
return f(*p, **kw)
return tracer
Die Funktion tracer_function_with_name
:
def tracer_function_with_name(f):
"Create a tracer function for f; preserve function name"
def tracer(*p, **kw):
print "TRACE:", f.func_name
return f(*p, **kw)
tracer.func_name = f.func_name
tracer.func_doc = f.func_doc
return tracer
Die Funktion tracer_function_with_name_and_dict
:
def tracer_function_with_name_and_dict(f):
"Create a tracer function for f; preserve function name and attrs."
def tracer(*p, **kw):
print "TRACE:", f.func_name
return f(*p, **kw)
tracer.func_name = f.func_name
tracer.func_doc = f.func_doc
tracer.__dict__.update(f.__dict__)
return tracer
Die Funktion tracer_function_with_update_wrapper
:
def tracer_function_with_update_wrapper(f):
"Create a tracer function for f; preserve attributes"
def tracer(*p, **kw):
print "TRACE:", f.func_name
return f(*p, **kw)
functools.update_wrapper(tracer, f)
return tracer
Das decorator-Modul¶
URLs:
- Dokumentation des decorator-Moduls
- decorator-2.2.0.zip (die Version, die im Buch benutzt wurde)
- decorator-2.3.1.zip (eine aktuellere Version – last checked 2008/07/31)
traced¶
Der traced
-Dekorator:
from decorator import decorator
@decorator
def traced(f, *p, **kw):
"A tracer decorator"
print "TRACE:", f.func_name
return f(*p, **kw)
Eine traced
Funktion doubler
:
@traced
def doubler(num):
"Returns the double of a number num"
return num + num
profiled¶
Der profiled
-Dekorator:
from decorator import decorator
from inspect import getargspec
@decorator
def profiled(f, *p, **kw):
"A call counter decorator"
if hasattr(f, "count"):
f.count = f.count + 1
else:
f.count = 1
print "PROFILER: %s called %d times(s)" % (f.func_name, f.count)
return f(*p, **kw)
Die Funktion doubler
jetzt profiled
:
@profiled
def doubler(num):
"Returns the double of number num"
return num + num
memoized¶
Der memoized
-Dekorator:
from decorator import decorator
from inspect import getargspec
@decorator
def memoized(f, *p):
"A memoizing decorator"
if not hasattr(f, "store"):
f.store = {}
if p in f.store:
return f.store[p]
else:
result = f(*p)
f.store[p] = result
return result
Die memoized
-Version von doubler
:
@memoized
def doubler(num):
"Doubles number num"
return num + num
Die Funktion timeme
:
import time
def timeme(f, *p):
"Compute and return f(p), and print time in seconds"
start_time = time.time()
result = f(*p)
end_time = time.time()
print "RUN TIME: %s took %.2f seconds" % (f.func_name,
end_time - start_time)
return result
Die Funktion fib1
:
def fib1(n):
"Computer fibonacci(n) recursively"
if n == 1 or n == 2:
return 1
else:
return fib1(n-1) + fib1(n-2)
Die Funktion fib2
:
@memoized
def fib2(n):
"Computer fibonacci(n) recursively"
if n == 1 or n == 2:
return 1
else:
return fib2(n-1) + fib2(n-2)
Die Funktion fast_pow
:
@memoized
def fast_pow(x, y):
"Compute pow(x, y) and cache the results"
return pow(x, y)
synchronized¶
Der synchronized
-Dekorator:
from decorator import decorator
import threading
@decorator
def synchronized(f, *p, **kw):
"Make a function synchronized in the Java sense"
lock = threading.Lock()
lock.acquire()
try:
result = f(*p, **kw)
finally:
lock.release()
return result
Die synchronisierte Funktion write
:
import time
@synchronized
def write(data):
"Writing to a single-access resouce"
time.sleep(1)
datalist.append(data)
Der delayed
-Dekorator:
from decorator import decorator
import threading
def delayed(nsec):
"A factory of decorators which launch a function after a delay"
def delayed_call(f, *p, **kw):
"Call f(*p, **kw) in a thread after a delay"
thread = threading.Timer(nsec, f, p, kw)
thread.start()
return thread
return decorator(delayed_call)
Ein verzögertes Schreiben:
@delayed(2)
def write_delayed(data):
write(data)
Der threaded
-Dekorator ist ein Sonderfall des delayed
-Dekorators:
>>> threaded = delayed(0)
Die Funktion long_computation
:
@threaded
def long_computation(maxval):
"Perform some long running computation"
i = 0
while i < maxval:
i = i + 1
print "Finished computation. Result: %d" % (i,)
return i
Screenshots:
URLs: