1.函数装饰器2. 类装饰器3. super关键字
1.函数装饰器
装饰器的定义:装饰器其实就是一个闭包,把一个函数当作参数传进去,然后返回一个替代版函数
装饰器主要的分类:
装饰器对无参数的函数进行装饰,对一个函数可以使用多个装饰器,执行顺序由内向外
#定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "" + fn() + ""
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "" + fn() + "" #当有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())
######执行结果
hello world - 1
hello world - 2
hello world - 3
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__
[, , , , , ]
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__
[, , , , , ]
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__
[, , , , , ]
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__
D.__init__
[, , , , , ]