装饰器实际上是一种设计模式,它的功能是给某个函数加一些功能,而不会动到原来已经写好的代码(是不是听起来像是遵循开闭原则)。
比较完备的装饰器写法是这样的:
def decorate_line(func):
def inner(*args, **kwargs):
print('-----------------')
return func(*args, **kwargs)
return inner
def decorate_star(func):
def inner(*args, **kwargs):
print('******************')
return func(*args, **kwargs)
return inner
@decorate_line
@decorate_star
def print_name():
print('vth')
这其实是运用了python的语法糖。
@decorate_line
这个就相当于以下代码:
print_name = decorate_line(print_name)
这个语法糖就是干了这个事儿。
一定要记住, @
后面跟的是一个装饰器,而不是装饰器的调用。
讲到这里,你也许会迷惑,装饰器到底是什么?
我认为比较好的定义是这样的:装饰器返回了一个闭包(啥是闭包?闭包是能够访问其他函数内部变量的函数)。调用这个闭包,会执行你想进行装饰的操作和你要装饰的函数。
在0x01中我们给出的代码,装饰器代码严重重复。我们发现可以用参数化的方式来实现代码重用。但由于语法糖的存在,我们无法给装饰器传递参数(语法糖默认将被装饰的函数当作唯一的参数传递给装饰器).
但记住,我们特别强调过, @
后面跟的是一个装饰器,所以,我们可以通过闭包的特点来使装饰器能够访问参数。
def get_decorate_shape(shape):
def real_decorate(func):
def inner(*args, **kwargs):
print(shape * 30)
return func(*args, **kwargs)
return inner
return real_decorate
@get_decorate_shape('*')
def print_name():
print('vth')
get_decorate_shape('*')
这一行其实是一个函数执行,它拿到了一个闭包,这个闭包就是我们要的装饰器。
闭包牛逼!!