1 def log(func): 2 def wrapper(*args, **kw): 3 print(‘call %s():‘ % func.__name__) 4 return func(*args, **kw) 5 return wrapper
之后如果在函数上方@log一下就相当于添加了log的功能
@log def now(): print(‘2015-3-25‘)
具体的意思是:
now = log(now)
也就是说now的函数地址传给了log,log return了wrapper,此时now的函数地址变为了闭包函数wrapper。
额,所以,对于装饰器个人观点就是wrapper对函数进行了闭包处理。
经过对函数的调试,我发现当出现@log的时候,会出现加载函数的过程。也就是外层的函数wrapper在没有now()运行的时候也照样加载了一遍,也就是这样:
def log(func): print(‘加载中。。。。。。。‘) def wrapper(*args, **kw): print(‘call %s():‘ % func.__name__) return func(*args, **kw) return wrapper @log def now(): print(‘index‘) print(f.__name__)
###############
加载中。。。。。。。
wrapper
所以这下都清楚了,@log就是一个now变为wrapper这样函数地址转移的过程,并且会运行wrapper函数外层的代码。
def one(file=‘txt‘): print(‘外层函数加载中。。。‘) def decorator(func): def wrapper(*args,**kw): print(‘出现了出现了,函数地址转移‘) return func(*args,**kw) return wrapper return decorator @one(‘txt‘) def f(): print("完成了,f=one(‘txt‘)(f)") f()
外层函数加载中。。。 出现了出现了,函数地址转移 完成了,f=one(‘txt‘)(f)
加了一层,但是不慌,原理还是那个原理。
f=one(‘txt‘)(f)
首先传参‘txt’,取到函数地址decorator,之后变为了f=decorator(f),是不是莫名的熟悉。
题目:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
db=‘db.txt‘ index={"name":None,"status":False} def log(filetype=‘txt‘): def decorator(func): def wrapper(*args,**kw): if index["name"] and index["status"]: return func(*args,**kw) if filetype==‘txt‘: name=input(‘请输入姓名‘).strip() password=input(‘请输入密码‘).strip() with open(db,encoding=‘utf8‘) as f: for line in f: dic=eval(line.strip()) if name in dic[‘user‘] and password in dic[‘password‘]: index[‘name‘]=name index[‘status‘]=True return func(*args,**kw) else: print("姓名或者密码输入错误") else: print(‘文件类型错误‘) return wrapper return decorator @log(‘txt‘) def f(a,b,c): res=a+b+c print(res) @log() def x(): print("认证功能成功") f(1,2,3) x()
稍微写的有点多了,但看懂并写出这一题的话,装饰器的基本使用应该没问题了。对于装饰器多功能的使用以后再补充吧。
原文:https://www.cnblogs.com/chengdz/p/12152428.html