5分钟掌握 Python 中的装饰器
裸睡的猪
共 7088字,需浏览 15分钟
·
2021-02-26 12:02
来源 | Python中文社区
import time
def timethis(func):
def inner(*args,**kwargs):
print('start timer:')
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print('end timer:%fs.'%(end - start))
return result
return inner
@timethis
def sleeps(seconds):
print(' sleeps begin:')
time.sleep(seconds)
print(' sleep %d seconds.\n sleeps over.'%seconds)
return seconds
print(sleeps(3))
start timer:
sleeps begin:
sleep 3 seconds.
sleeps over.
end timer:3.002512s.
3
一、理解@标识符
@timethis
def sleeps(seconds):
print(' sleeps begin:')
time.sleep(seconds)
print(' sleep %d seconds.\n sleeps over.'%seconds)
return seconds
def sleeps(seconds):
print(' sleeps begin:')
time.sleep(seconds)
print(' sleep %d seconds.\n sleeps over.'%seconds)
return seconds
sleeps = timethis(sleeps)
二、装饰器是一个函数
根据上文timethis装饰器的定义,它毫无疑问是一个函数。名称是timethis,参数是func,返回值是inner。 根据 sleeps = timethis(sleeps)
,可知参数func是被装饰的函数sleeps。根据 return inner
,可知返回值inner是嵌套定义在装饰器中的一个函数。
三、函数是一等对象
3.1运行时创建
>>> def reverse(word):
... return word[::-1]
...
>>> reverse
<function reverse at 0x027A4C40>
>>> reverse('hello world!')
'!dlrow olleh'
3.2可赋值给变量或数据结构
>>> backward=reverse
>>> backward('hello world!')
'!dlrow olleh'
3.3函数作为参数传递
cars = ['Honda','toyota','hyundai','byd','ford','suzuki','peuguot','nissan','citroen','kia','vw','gm','audi','bmw','beniz']
print(sorted(cars,key=reverse))
['Honda', 'kia', 'toyota', 'ford', 'byd', 'hyundai', 'audi', 'suzuki', 'gm', 'nissan', 'citroen', 'peuguot', 'bmw', 'vw', 'beniz']
3.4函数作为返回值返回
def cmpLib():
def reverse(word):
return word[::-1]
return reverse
print(sorted(cars,key=cmpLib())
['Honda', 'kia', 'toyota', 'ford', 'byd', 'hyundai', 'audi', 'suzuki', 'gm', 'nissan', 'citroen', 'peuguot', 'bmw', 'vw', 'beniz']
def inner(*args,**kwargs):
的参数命名形式呢?四、可接受任意数量参数的函数
def inner(*args,**kwargs):
是约定俗成的固定写法。来看个例子就可以理解这种写法了。def star(*args,**kwargs):
print(args,kwargs)
star(1,2,3)
star(4,5,name='zhang')
star(7,name='lisi',gender='m')
输出结果:
(1, 2, 3) {}
(4, 5) {'name': 'zhang'}
(7,) {'name': 'lisi', 'gender': 'm'}
五、增强被装饰函数的行为
print('start timer:')
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print('end timer:%fs.'%(end - start))
result = func(*args,**kwargs)
前后,包裹上相应的计时功能。六、变量作用域
b=3
def func(a):
print(a)
print(b)
b=2
func(2)
让我们猜猜运行结果,应该是1,3对吧,但执行却提示出错:
File "dec.py", line 47, in func
print(b)
UnboundLocalError: local variable 'b' referenced before assignment
七、闭包
八、返回值和返回函数
第一个返回值,返回的是func的执行结果,它属于inner函数的返回值,等效于sleeps函数的返回值,这是sleep函数的应有之意。保持了原函数sleeps对外结构的一致性。 第二个返回值是inner函数本身,也就是第三部分讲述的函数作为返回结果的用法。依据slepps=timethi(sleeps)语法,其返回结果是inner函数,传递给sleeps函数,使sleeps函数实际上等同于inner函数。所以调用sleeps(3)相当于调用inner(3)。再加上围绕他的计时功能,故而无损增加了计时功能。
评论