# For debugging, the stacktrace prints you the function __name__
deffoo():
print"foo"
print foo.__name__
#outputs: foo
# decorator会隐藏实际的函数名
defbar(func):
defwrapper():
print"bar"
return func()
return wrapper
@bar
deffoo():
print"foo"
# 返回的时wrapper。但是明明实际的函数是foo啊。
print foo.__name__
#outputs: wrapper
# functools可以帮我们解决这个问题
import functools
defbar(func):
# We say that "wrapper", is wrapping "func"
# and the magic begins
@functools.wraps(func)
defwrapper():
print"bar"
return func()
return wrapper
@bar
deffoo():
print"foo"
print foo.__name__
#outputs: foo
decorator到底有什么用处?
典型的应用:
为一个你不能修改的lib添加一些功能
用于调试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
defbenchmark(func):
"""
A decorator that prints the time a function takes
to execute.
"""
import time
defwrapper(*args, **kwargs):
t = time.clock()
res = func(*args, **kwargs)
print func.__name__, time.clock()-t
return res
return wrapper
deflogging(func):
"""
A decorator that logs the activity of the script.
(it actually just prints it, but it could be logging!)
"""
defwrapper(*args, **kwargs):
res = func(*args, **kwargs)
print func.__name__, args, kwargs
return res
return wrapper
defcounter(func):
"""
A decorator that counts and prints the number of times a function has been executed
"""
defwrapper(*args, **kwargs):
wrapper.count = wrapper.count + 1
res = func(*args, **kwargs)
print"{0} has been used: {1}x".format(func.__name__, wrapper.count)
return res
wrapper.count = 0
return wrapper
@counter
@benchmark
@logging
defreverse_string(string):
return str(reversed(string))
print reverse_string("Able was I ere I saw Elba")
print reverse_string("A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!")
#outputs:
#reverse_string ('Able was I ere I saw Elba',) {}
#wrapper 0.0
#wrapper has been used: 1x
#ablE was I ere I saw elbA
#reverse_string ('A man, a plan, a canoe, pasta, heros, rajahs, a coloratura, maps, snipe, percale, macaroni, a gag, a banana bag, a tan, a tag, a banana bag again (or a camel), a crepe, pins, Spam, a rut, a Rolo, cash, a jar, sore hats, a peon, a canal: Panama!',) {}
#wrapper 0.0
#wrapper has been used: 2x
#!amanaP :lanac a ,noep a ,stah eros ,raj a ,hsac ,oloR a ,tur a ,mapS ,snip ,eperc a ,)lemac a ro( niaga gab ananab a ,gat a ,nat a ,gab ananab a ,gag a ,inoracam ,elacrep ,epins ,spam ,arutaroloc a ,shajar ,soreh ,atsap ,eonac a ,nalp a ,nam A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@counter
@benchmark
@logging
defget_random_futurama_quote():
from urllib import urlopen
result = urlopen("http://subfusion.net/cgi-bin/quote.pl?quote=futurama").read()
try:
value = result.split("<br><b><hr><br>")[1].split("<br><br><hr>")[0]