1.函数装饰器
-
装饰器的定义:装饰器其实就是一个闭包,把一个函数当作参数传进去,然后返回一个替代版函数
-
装饰器主要的分类:
-
装饰器对无参数的函数进行装饰,对一个函数可以使用多个装饰器,执行顺序由内向外
#定义函数:完成包裹数据 def makeBold(fn): def wrapped(): return "<b>" + fn() + "</b>" return wrapped #定义函数:完成包裹数据 def makeItalic(fn): def wrapped(): return "<i>" + fn() + "</i>" #当有return时,适用于有返回和无返回的函数 return wrapped @makeBold def test1(): return "hello world - 1" @makeItalic def test2(): return "hello world - 2" @makeBold @makeItalic def test3(): return "hello world - 3" print(test1()) print(test2()) print(test3()) ######执行结果 <b>hello world - 1</b> <i>hello world - 2</i> <b><i>hello world - 3</i></b> Process finished with exit code 0
-
装饰器对有参数函数进行装饰
#定义一个装饰器 def deco(func): # 内部函数的参数必须和被装饰的函数保持一致 def wrapper(a, b): print("获得被修饰函数的参数:a= %s,b= %s" % (a, b)) return func(a, b) return wrapper #有参数的函数 @deco def sum(a, b): return a+b print(sum(10, 20)) ######执行结果 获得被修饰函数的参数:a= 10,b= 20 30 Process finished with exit code 0
-
装饰器对可变参数函数进行装饰
#定义一个装饰器,装饰不定长参数函数 def deco(func): def wrapper(*args,**kwargs): print("arguments args length : %d" % len(args)) print("arguments kwargs length : %d" % len(kwargs)) func(*args,**kwargs) return wrapper @deco def test1(a, b, c): print(a+b+c) @deco def test2(a, b): print(a+b) @deco def test3(*args,**kwargs): print(args) print(kwargs) print("*************") test1(10, 20, 30) print("*************") test2(10, 20) print("*************") test3(1, 2, 3, d=4, x=5) ######执行结果 ************* arguments args length : 3 arguments kwargs length : 0 60 ************* arguments args length : 2 arguments kwargs length : 0 30 ************* arguments args length : 3 arguments kwargs length : 2 (1, 2, 3) {'d': 4, 'x': 5} Process finished with exit code 0
-
带参数的装饰器
def decrorator_args_func(): print("This is a warpper function") def decrorator_func(decrorator_func_arg): decrorator_func_arg() def decr_outter_func(func): def decr_inner_func(*args,**kwargs): func(*args,**kwargs) print("I am a decrorator inner function") return decr_inner_func return decr_outter_func @decrorator_func(decrorator_args_func) def warpped_func(a, b): print("I am a wapped function") warpped_func('s', 'b') ######执行结果 This is a warpper function I am a wapped function I am a decrorator inner function Process finished with exit code 0
-
-
如果多个函数被两个装饰器装饰时就报错,因为两个函数名一样,第二个函数再去装饰的话就报错。增加@functools.wraps(f), 可以保持当前装饰器去装饰的函数的 name 的值不变
import functools def user_login_data(f): @functools.wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) return wrapper @user_login_data def num1(): print("aaa") @user_login_data def num2(): print("bbbb") if __name__ == '__main__': print(num1.__name__) print(num2.__name__) ######执行结果 num1 num2 Process finished with exit code 0
2. 类装饰器
-
类装饰器概念:类装饰器的装饰方法跟函数装饰器相同,都是使用@语法,但是由于类本身不可直接被调用执行,因此必须在类中实现call( )方法。
-
类装饰器的分类:
-
装饰无参数的类装饰器
# 仅执行函数 class FuncLog(): def __init__(self, func): print('exec funcLog __init__') self._func = func # 类装饰器中,要有call方法 def __call__(self): print('exec funcLog __call__') return self._func() #当有return时,适用于有返回和无返回的函数 @FuncLog def demoFunc(): print( 'This is a demo function......') @FuncLog def demoFunc2(): return 'This is a demo function......' demoFunc() print(demoFunc2()) #########执行结果 exec funcLog __init__ exec funcLog __init__ exec funcLog __call__ This is a demo function...... exec funcLog __call__ This is a demo function.....1111. Process finished with exit code 0
-
装饰有参数的类装饰器
# 执行函数,被修饰函数存在参数 class FuncLog(): def __init__(self, func): print('exec funcLog __init__') self._func = func # 类装饰器中,要有call方法 def __call__(self, *args, **kwargs): print('exec funcLog __call__') print('function args : %s '% args) self._func(*args, **kwargs) @FuncLog def demoFunc(func_args): print('This is a demo function, Args is : %s' % func_args) demoFunc('20190726') #########执行结果 exec funcLog __init__ exec funcLog __call__ function args : 20190726 This is a demo function, Args is : 20190726 Process finished with exit code 0
-
装饰有参数的类装饰器,并且装饰器有参数
import functools # 执行函数,被修饰函数存在参数,并且装饰器有入参 class FuncLog(): def __init__(self, func_log_arg): print('exec funcLog __init__') self._func_log_arg = func_log_arg # 类装饰器中,要有call方法 def __call__(self, func): print('exec funcLog __call__') print('decr args is :%s' % self._func_log_arg) @functools.wraps(func) def wrapper(*args, **kwargs): print('function args : %s ' % args) return func(*args, **kwargs) return wrapper @FuncLog('decr_log') def demoFunc(func_args): print('This is a demo function, Args is : %s' % func_args) demoFunc('20190726') print(demoFunc.__name__) ###########执行结果 exec funcLog __init__ exec funcLog __call__ decr args is :decr_log function args : 20190726 This is a demo function, Args is : 20190726 demoFunc Process finished with exit code 0
-
3. super关键字
-
定义: super([type[, object-or-type]]) ,super() 在使用时至少传递一个参数,且这个参数必须是一个类。通过super()获取到的是一个代理对象,通过这个对象去查找父类或者兄弟类的方法。
-
集中常用的写法:
-
super()不写参数的情况:super() 在一个定义的类中使用时,可以不写参数,Python会自动根据情况将两个参数传递给super。在Python3中的类都是新式类,广度优先的查找顺序,在定义一个类时就会生成一个MRO列表(经典类没有MRO列表,深度优先),查找顺序就是按照这个列表中的类的顺序从左到右进行的。
class Base: def __init__(self): print('Base.__init__') class A(Base): def __init__(self): super().__init__() print('A.__init__') class B(Base): def __init__(self): super().__init__() print('B.__init__') class C(Base): def __init__(self): super().__init__() print('C.__init__') class D(A, B, C): def __init__(self): super().__init__() # 等同于 super(D, self).__init__() print('D.__init__') D() print(D.mro()) #结果 Base.__init__ C.__init__ B.__init__ A.__init__ D.__init__ [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>]
-
super(type) 只传递一个参数的情况:super() 只传递一个参数时,是一个不绑定的对象,不绑定的话它的方法是不会有用的
class Base: def __init__(self): print('Base.__init__') class A(Base): def __init__(self): super().__init__() print('A.__init__') class B(Base): def __init__(self): super().__init__() print('B.__init__') class C(Base): def __init__(self): super().__init__() print('C.__init__') class D(A, B, C): def __init__(self): super(B).__init__() # 值传递一个参数 print('D.__init__') D() print(D.mro()) #结果 D.__init__ [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>]
-
super(type, obj) 传递一个类和一个对象的情况:super() 的参数为一个类和一个对象的时候,得到的是一个绑定的super对象。但是obj必须是type的实例或者是子类的实例。 从结果可以看出,只是查找了B类之后的类的方法,即super()是根据第二个参数(obj)来计算MRO,根据顺序查找第一个参数(类)之后的类的方法
class Base: def __init__(self): print('Base.__init__') class A(Base): def __init__(self): super().__init__() print('A.__init__') class B(Base): def __init__(self): super().__init__() print('B.__init__') class C(Base): def __init__(self): super().__init__() print('C.__init__') class D(A, B, C): def __init__(self): super(B, self).__init__() # self是B的子类D的实例 print('D.__init__') D() print(D.mro()) #结果 Base.__init__ C.__init__ D.__init__ [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>]
-
super(type1, type2) 传递两个类的情况:super()传递两个类type1和type2时,得到的也是一个绑定的super对象,但这需要type2是type1的子类,且如果调用的方法需要传递参数时,必须手动传入参数,因为super()第二个参数是类时,得到的方法是函数类型的,使用时不存在自动传参,第二个参数是对象时,得到的是绑定方法,可以自动传参。
class Base: def __init__(self): print('Base.__init__') class A(Base): def __init__(self): super().__init__() print('A.__init__') class B(Base): def __init__(self): super().__init__() print('B.__init__') class C(Base): def __init__(self): super().__init__() print('C.__init__') class D(A, B, C): def __init__(self): super(B, D).__init__(self) # D是B的子类,并且需要传递一个参数 print(type(super(B, D).__init__)) #返回的Function,需要自己填充参数 print(type(super(B, self).__init__)) #返回的是method,python自动填充参数 print('D.__init__') D() print(D.mro()) #结果 Base.__init__ C.__init__ <class 'function'> <class 'method'> D.__init__ [<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Base'>, <class 'object'>]
-