装饰器刚开始比较难理解,写代码时不是不会写,而是不知道要去怎么实现功能,因为不仅要实现功能,而且要尽可能优化代码。先上一个无参数的简单的装饰器代码。
#!/usr/bin/python3
d=dict()
def dic(f):
def dic1(*key,**value):
d[f.__name__]=f
return dic1
@dic
def add():
print('add numbers:')
add()
@dic
def ip():
print('your ip address is 172.16.2.4')
ip()
while True:
c=input('root@localhost~:')
if c=='quit':
break
if c not in d:
print('this command does not exist')
else:
d[c]()
这个是一个简单的命令分发器,装饰器dic函数主要是用来将其他函数内容加到字典里,下面再给每个函数调用装饰器,标准格式是定义函数上一行要@装饰器函数,写完之后要再调用函数,相当于在装饰器里调用每个函数,进行一个功能的包装。
后面几天,用两个装饰器去装饰一个函数,来达成目标,因为用完装饰器后,再输出函数的信息就都变成了装饰器的信息,所以为了避免不必要的麻烦,就要解决这个问题。先附上我的代码。
#!/usr/bin/python3
def fun1(f):
def wapper1(*a):
print(f.__name__)
print(f.__doc__)
return f(*a)
return wapper1
def fun(f):
def wapper(*args):
'''this is a wapper1'''
return f(*args)
return wapper
@fun
@fun1
def add(x,y):
'''this is a add function'''
return x+y
print(add(4,5))
我自己写的时候是这样调用装饰器的,这种调用时很注重装饰器调用的位置,先调用的装饰器一定要放在下面一行,这样才会不出问题。这种就相当于高阶函数,一个装饰器套一个,刚开始写的时候思绪很乱,后来自己在纸上写了写函数调用的过程,大概就明白了,就相当于fun(fun1(add))。不过Python里自带了 @functools.wraps(fn) 的装饰器,就可以直接对被调用函数进行函数信息的调整。
再有一个就是在调用装饰器时就传入参数,这样在一些特定的需求的系统里就会方便很多,先上代码。
#!/usr/bin/python3
import datetime
def time(t):
def fun(f):
def wapper():
now=datetime.datetime.now().timestamp()
a=f()
delta=datetime.datetime.now().timestamp()-now
if delta>float(t*60):
print('more than {} minutes'.format(t))
else:
print('no more than {} minutes'.format(t))
return delta
return wapper
return fun
@time(1)
def run():
lst=[i for i in range(1000000)]
print(run())
这种代码就和上面的代码是一种思维,一般的装饰器都是在外层函数里调用一个函数作为参数,内层再做相关的操作。而这个也是一样,只是在普通的装饰器最外面再柯林化一个函数,用来接收参数,再return内层的函数,这样来达到用装饰器传参的目的,只要掌握高阶函数和基本的装饰器,后面的东西就会很容易联想到,一个套一个的,照猫画老虎,再写起代码来就不会费劲。
参数注解比较容易理解和掌握,只是相关函数的调用比较多,直接上代码吧,具体的函数关系和函数作用太多,需要自己去记常用的。
#!/usr/bin/python3
import inspect
def fun(f):
def wrapper(*args,**kwargs):
sig=inspect.signature(f)
val=list(sig.parameters.values())
for k,v in enumerate(args):
if str(val[k].annotation)=="<class 'inspect._empty'>":
print('No problem')
continue
if isinstance(v,val[k].annotation):
print('No problem')
else:
print('input error')
return wrapper
@fun
def add(x,y:int=7):
return x+y
add(2,3)
add(3,'u')
add(11,'J')