#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 学习网站:www.liaoxuefeng.com
#****************************************************
# Python3 函数式编程-装饰器 *
#****************************************************
print ("--------------------分割线------------------")
#============
# 装饰器Decorator
#============
# 函数对象赋值给变量,通过变量也能调用该函数。
def now():
print('today is sunday')
fun1 = now
fun1() # today is sunday
# 函数对象的__name__属性
print( now.__name__, fun1.__name__ ) # now now
'''
假设增强now()函数的功能,比如在函数调用前后自动打印日志,但又希望
修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称为
装饰器(Decorator)
本质上,decorator就是一个返回函数的高阶函数,所以定义一个能打印日志的
decorator。
'''
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
# log()函数是一个decorator,所以接受一个函数作为参数,并返回一个函数
# 使用@语法,把decorator置于函数的定义处:
@log
def today():
print('today is 2018-03-14')
today()
'''
函数执行结果:
call today():
today is 2018-03-14
'''
'''
把@log放到today()函数的定义处,相当于执行today = log(today)
由于log()是一个decorator,返回一个函数,所以原来的today函数仍然存在
只是现在同名的变量指向了新的函数,于是调用today()将执行新函数,即在
log()函数中返回的wrapper()函数
wrapper()函数的参数定义是(*args, **kw),因此wrapper()函数可以接受任意
参数的调用,在wrapper()函数内,先打印日志,再调用原始函数。
'''
print ("--------------------分割线------------------")
'''
如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数
'''
# 自定义Log的文本,3层嵌套的decorator
def Log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@Log('execute')
def hel():
print('hello Bugliu')
hel()
'''
执行结果:
execute hel():
hello Bugliu
'''
'''
解析:
hel() 相当于 hel = log('execute')(now)
首先执行log('execute'),返回的是decorator函数,再调用返回的函数,
参数是now函数,返回值最终是wrapper函数。
'''
print ("--------------------分割线------------------")
print( hel.__name__ ) # wrapper
# 经过decorator装饰之后,函数对象的__name__属性从原来的'hel'变成了
# ‘warpper’,因为返回的那个wrapper()函数名字就是'wrapper',所以需要把
# 原始函数的__name__属性复制到wrapper()函数中,否则,有些依赖函数签名
# 的代码执行就会出错
# 可以使用内置的functools.wraps,完整的decorator
import functools
def LOG(text):
def decorator(func):
@functools.wraps(func) # 增加此行可解决属性问题
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@LOG('正在执行')
def hel():
print('hello Bugliu')
hel()
print( hel.__name__ )
'''
执行结果:
正在执行 hel():
hello Bugliu
hel
'''
print ("--------------------分割线------------------")
# 请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:
import time
import functools
def metric(func):
@functools.wraps(func)
def wrapper(*args,**kw):
startTime = time.time()
test = func(*args,**kw)
endTime = time.time()
t = endTime - startTime
print('executed in %s ms' % t)
return test
return wrapper
@metric
def fast(x, y):
time.sleep(0.0012)
return x + y;
@metric
def slow(x, y, z):
time.sleep(0.1234)
return x * y * z;
f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
print('测试失败!')
elif s != 7986:
print('测试失败!')
'''
执行结果:
executed in 0.0025014877319335938 ms
executed in 0.1245872974395752 ms
'''
print ("--------------------分割线------------------")
"""
写出一个@log的decorator,使它既支持:
@log
def f():
pass
又支持:
@log('execute')
def f():
pass
"""
def log(arg):
def inner_log(text='call'):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
if callable(arg):
return inner_log()(arg)
return inner_log(arg)
@log
def f():
pass
@log('execute')
def f2():
pass
f() # call f():
f2() # execute f2():
Python3 学习笔记24_函数式编程-装饰器_20180314
最新推荐文章于 2021-08-04 11:42:53 发布