# 装饰器就是一个将其他函数(也就是被装饰的函数)作为参数的一个function
def my_shiny_new_decorator(a_function_to_decorate):
# 在这个装饰器函数里面用另外一个函数来包装原函数,
# 即在调用原来的函数前后分别执行其他的操作.
def the_wrapper_around_the_original_function():
# 这里放一些你希望在原来的函数执行之前的代码,例如log、身份验证等
print "Before the function runs"
# 调用原函数本身,注意有()
a_function_to_decorate()
#同理,这里放一些你希望在原来的函数执行之后的代码,例如释放资源等
print "After the function runs"
# 注意,此时,函数 "a_function_to_decorate"并没有被执行.
# 此时将刚刚创建的用来包装原函数的函数返回
return the_wrapper_around_the_original_function
# 假设你定义了一个函数,并良好实现,也觉得perfect了。且发誓以后并不准备改动这段代码
def a_stand_alone_function():
print "I am a stand alone function, don't you dare modify me"
a_stand_alone_function()
#输出: I am a stand alone function, don't you dare modify me
# 有时候,作为coder,并不是你不动代码就能不动的。PM此时另外又来了个需求,让你在之前
#的基础上再加点XX功能,苦逼的程序猿乖乖的改吧。不过有了装饰器,你能满足PM的需求,又能不违背
#当初许下的不改变原有代码的誓言。仅仅需要将此函数拿去重新装饰一下即可。如下:
a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function_decorated()
#输出:
#Before the function runs
#I am a stand alone function, don't you dare modify me
#After the function runs
@my_shiny_new_decorator
def another_stand_alone_function():
print "Leave me alone"
another_stand_alone_function()
#Before the function runs
#Leave me alone
#After the function runs
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print "传进来的参数是:", arg1, arg2
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# 既然你调用了装饰过后的函数,你也就调用了包装器,函数也就自然传递到了包装器。
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print "My name is", first_name, last_name
print_full_name("lei", "tang")
# 输出:
#传进来的参数是: lei tang
#My name is lei tang
装饰类中的方法
python中的方法和函数差不多,只不过类中的方法的第一个参数是当前对象的引用self。
def method_friendly_decorator(method_to_decorate):
def wrapper(self, lie):
lie = lie - 3 #减少3
return method_to_decorate(self, lie)
return wrapper
class Lucy(object):
def __init__(self):
self.age = 32
@method_friendly_decorator
def sayYourAge(self, lie):
print "I am %s, what did you think?" % (self.age + lie)
l = Lucy()
l.sayYourAge(-3)#32-3 -3(wrapper中还减了3岁)=26
#输出: I am 26, what did you think?
def a_decorator_passing_arbitrary_arguments(function_to_decorate):
# 包装器接受任意参数
def a_wrapper_accepting_arbitrary_arguments(*args, **kwargs):
print "Do I have args?:"
print args
print kwargs
#*args代表没有给定默认值的参数列表(arg1,arg2,……),**kwwars代表有给定默认值(arg1=val1,arg2=val2,……)
function_to_decorate(*args, **kwargs)
return a_wrapper_accepting_arbitrary_arguments
@a_decorator_passing_arbitrary_arguments
def function_with_no_argument():
print "Python is cool, no argument here."
function_with_no_argument()
#输出
#Do I have args?:
#()
#{}
#Python is cool, no argument here.
@a_decorator_passing_arbitrary_arguments
def function_with_arguments(a, b, c):
print a, b, c
function_with_arguments(1,2,3)
#输出
#Do I have args?:
#(1, 2, 3)
#{}
#1 2 3
@a_decorator_passing_arbitrary_arguments
def function_with_named_arguments(a, b, c, platypus="Why not ?"):
print "Do %s, %s and %s like platypus? %s" %(a, b, c, platypus)
function_with_named_arguments("Bill", "Linus", "Steve", platypus="Indeed!")
#输出
#Do I have args ? :
#('Bill', 'Linus', 'Steve')
#{'platypus': 'Indeed!'}
#Do Bill, Linus and Steve like platypus? Indeed!
class Mary(object):
def __init__(self):
self.age = 31
@a_decorator_passing_arbitrary_arguments
def sayYourAge(self, lie=-3): # You can now add a default value
print "I am %s, what did you think ?" % (self.age + lie)
m = Mary()
m.sayYourAge(8)
m.sayYourAge(lie=-8)#注意看下面print出的**kwargs区别
#输出
#Do I have args?:
#(<__main__.Mary object at 0x01228430>, 8)
#{}
#I am 39, what did you think ?
#Do I have args?:
#(<__main__.Mary object at 0x01228430>,)
#{'lie': -8}
#I am 23, what did you think ?
# 装饰器函数也是function
def my_decorator(func):
print "I am a ordinary function"
def wrapper():
print "I am function returned by the decorator"
func()
return wrapper
def lazy_function():
print "zzzzzzzz"
decorated_function = my_decorator(lazy_function)
#输出: I am a ordinary function
#注意此时,被装饰的函数并没有调用。
#同样,用@的方式也得到相同的结果
@my_decorator
def lazy_function():
print "zzzzzzzz"
#输出: I am a ordinary function
#当@的时候,就告诉python去调用装饰器函数。这个@后的标签很重要,直接指向装饰器