装饰器一直以来就是一个晦涩难懂的内容,这里如何快速的学会写装饰器,可以就像背课文一样,以后再寻求理解。
目前接触的两类装饰器有类装饰器和函数装饰器(应用与方法的装饰器有一点点不同)
函数装饰器
函数装饰器可以这样分:
- 装饰器不带参数,函数也不带参数。
#函数和装饰器都不带参数
def recall(func):
def wrap():
func()
func()
return wrap
@recall
def print_hello():
print('hello')
print_hello()
这段代码装饰器recall的作用是复读一次被装饰函数,@只是python的神奇用法@recall在这里只是相当于recall(print_hell) 返回的对象假设它是A,再通过A()调用。相当于以下代码。
def recall(func):
def wrap():
func()
func()
return wrap
def print_hello():
print('hello')
A = recall(print_hello)
A()
2.函数带参数,装饰器不带参数。
#函数带参数,装饰器不带。
def recall(func):
def wrap(str):
func(str)
func(str)
return wrap
@recall
def print_hello(str):
print(str)
print_hello('你好')
与函数不带参数的区别是装饰器内部定义wrap函数做出相应改变才能接受参数,其实就是返回出的wrap对象代替了原本的print_hello对象。
装饰方法的装饰器要记住方法的第一个参数是self,所以装饰器也要对应加上self参数。
3.装饰器带参数。
装饰器带参数后,函数带不带参数没有什么特别的,下面是一段简单的装饰器带参数的例子。
# 装饰器带参数。
def arg_here(args):
print('{}在recall之外'.format(args[0]))
def recall(func):
print('{}在wrap之外'.format(args[0]))
def wrap(str):
print('{}在wrap之下'.format(args[0]))
func(str)
func(str)
return wrap
return recall
@arg_here('我是装饰器参数')
def print_hello(str):
print(str)
print_hello('你好')
装饰器带参数,把原来的装饰器用另外一个函数包住,并留下参数的空间,就可以把装饰器的参数引入进来。
类装饰器
类装饰器是在不修改原类代码的情况下,能对代码做一定的扩展,以下就是一个装饰器不带参数的类装饰器。
# 不带参数类装饰器
def add_scool(obj):
obj.scool = '大学'
def print_scool(self):
print(self.scool)
obj.print_scool = print_scool
return obj
@add_scool
class Student(object):
pass
a = Student()
a.print_scool()
可以这样想,当对象创建完毕还没执行__init__方法,对象不返回给a而是传给obj执行装饰,装饰完毕之后再返回给a。
还有装饰器带参数的用法。
def add_args(*args):
print(args)
def add_scool(obj):
obj.scool = '大学'
def print_scool(self):
print(self.scool)
obj.print_scool = print_scool
return obj
return add_scool
@add_args(1)
class Student(object):
def __init__(self):
print(1)
a = Student()
a.print_scool()
与函数装饰器一样,用另外的方法包住原来的代码就可以把参数传进来了。
装饰器的经典用法是从外部库扩展函数行为(您不能修改它),或者用于调试(您不想修改它,因为它是临时的)。
您可以使用它们以DRY的方式扩展多个功能
装饰器的好处在于你几乎可以在没有重写的情况下立即使用它们。
Python本身提供了一些装饰:property,staticmethod,等。
Django使用装饰器来管理缓存和查看权限。
扭曲伪造内联异步函数调用。
我这样想可能并不是特别清楚,但是会用就可以了,以后想起来了可以多琢磨琢磨其中的奥秘。