装饰器的相关知识点
1. 装饰器的原理及为什么要用装饰器
装饰器原理:在不修改源代码,不修改调用方式的基础上扩展新功能
开放封闭原则:软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的。也就是说我们必须找到一种解决方案:能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能。
1. 装饰器的基本用法
def outer(func):
def inner(*args,**kwargs):
res=func(*args,**kwargs)
return res
return inner
1. 带参数的装饰器
再包上一层,函数的参数可以为一个,也可为多个
def auth(engine):
def auth2(func):
def wrapper(*args,**kwargs):
if engine=='file':
if current_user['username']:
print('login already')
res=func(*args,**kwargs)
return res
uname=input('username>>: ').strip()
pwd=input('password>>: ').strip()
if uname=='egon' and pwd=='123':
print('login successfully')
current_user['username']=uname
res=func(*args,**kwargs)
return res
else:
print('wrong username or password')
elif engine=='mysql':
print('based on mysql')
elif engine=='idap':
print('based on ldap')
return wrapper
return auth2
@auth('mysql')
def f():
pass
f()
1. 被装饰的函数有返回值怎么处理
res=func(*args,**kwargs)
return res
1. 多个装饰器的执行顺序
叠加多个装饰器,上面的装饰器的作用为: 下方装饰器+原函数
装饰器函数的执行顺序是分为定义阶段和执行阶段的,装饰器函数在被装饰函数定义好后立即执行
- 在函数定义阶段:执行顺序是从最靠近函数的装饰器开始,自内而外的执行
- 在函数执行阶段:执行顺序由外而内,一层层执行
6. 装饰类的装饰器
@classmethod
将被装饰的函数变成绑定给类的方法;应该由类来调用,会主动将类作为第一个参数传入
@staticmethod
将被装饰的函数变成非绑定方法;既不跟类绑定,也不跟对象绑定,这意味着谁都能用;谁来用都是一个普通函数,也就是说没有自动传值的特性了
7、 装饰器修复技术
from functools import wraps (强烈推荐写上这一行)
def wrapper(func):
# 装饰器修复技术
@wraps(func)
def inner(*args, **kwargs):
print("start")
ret = func(*args, **kwargs)
print("end")
return ret
return inner
@wrapper
def f(*args, **kwargs):
"""
这是一个测试装饰器的函数,没什么其他的用法
:param args:
:param kwargs:
:return:
"""
print("2018-06-04")
f()
print(f.__doc__) # 如果不加装饰器的修复技术,打出的inner函数的__doc__
print(f.__name__) # 如果不修复,打出的是inner