装饰器相关
对于函数:
import time
def test1():
time.sleep(0.5)
print('test---1')
if __name__ == '__main__':
test1()
此时想要增加一个运行计时功能,可以:
def test1():
start_time = time.time()
time.sleep(0.5)
print('test---1')
print('消耗时间:', time.time() - start_time)
if __name__ == '__main__':
test1()
这样写改变了代码原来的结构,对于完成度比较高的代码,如果需要增加功能,尽量不要改变它的结构。
想要在不改变原来的函数结构情况下增加功能,就可以使用装饰器:
import time
def decorator(func):
def wapper():
start_time = time.time()
func()
print('消耗时间:', time.time() - start_time)
return wapper
@decorator
def test1():
time.sleep(0.5)
print('test---1')
@decorator
def test2():
time.sleep(0.5)
print('test---2')
if __name__ == '__main__':
test1()
test2()
当函数比较多就可以看出装饰器的方便,还节省了代码量
执行test1()
时,相当于执行了 decorator(test1)
关于装饰器的执行:
def fun_out(fun):
def fun_in():
print('decorator')
fun()
print(id(fun_in))
return fun_in
@fun_out
def fun_1():
print('fun_1')
fun_1()
fun_out(None)
print('fun_1函数id:', id(fun_1), ' fun_1函数名:', fun_1.__name__)
'''
@fun_out相当于执行下面的操作
fun_1 = fun_out(fun = fun_1) 相当于赋值操作,fun_1 指向了fun_out(),()代表执行,所以下面的函数会执行
def fun_in(): 在这里定义了fun_in,定义但不执行,此时fun_1 仍然 = print('fun_1)
print('decorator')
fun = fun_1() print('fun_1)
return fun_in 执行完毕,返回了fun_in,即fun_1 = fun_in,此时fun_1已经不是原来的print('fun_1')
= fun_in fun_1 = fun_in,fun_1不是原来的 print('fun_1')
调用
fun_1() = fun_in() = print('decorator')
print('fun_1)
'''
多重装饰器
def makeBold(fn):
# def wrapped():
# return "<b>" + fn() + "</b>"
# fn()执行ruturn,ruturn 执行过之后,wrapped 在makeBold 函数里面意为字符串"<b>" + fn() + "</b>"
# return wrapped
return lambda: ("<b>" + fn() + "</b>")
def makeItalic(fn):
return lambda: ("<i>" + fn() + "</i>")
@makeBold
def test1():
return "test-1"
@makeItalic
def test2():
return "test-2"
@makeBold
# @makeBold发现下面不是一个函数,暂停执行
@makeItalic
# @makeItalic发现下面是test3(),执行
def test3():
return "test-3"
print(test1())
print(test2())
print(test3())
print((lambda: 50 * '-')())
装饰类方法
import time
def decorator(func):
def wapper():
start_time = time.time()
func()
print(time.time() - start_time)
return wapper
class MyObj(object):
def __init__(self, content):
self.content = content
@decorator
def run(self):
time.sleep(0.5)
print(self.content)
if __name__ == '__main__':
obj = MyObj('你好')
obj.run()
此时会报错误:wapper() takes 0 positional arguments but 1 was given
,也就是说wapper()
传入了一个参数,原因:对于类方法,会默认传入一个self
,表示实例对象,也就是说decorator(func)(self)
def decorator(func):
def wapper(self):
start_time = time.time()
self()
print(time.time() - start_time)
return wapper
class MyObj(object):
def __init__(self, content):
self.content = content
@decorator
def run(self):
time.sleep(0.5)
print(self.content)
# __call__() 把对象转为可执行
def __call__(self, *args, **kwargs):
print('call-------------')
if __name__ == '__main__':
obj = MyObj('你好')
obj.run()
运行结果
call-------------
0.0
可见执行了__call__(),所以装饰类方法应该:
def decorator(func):
def wapper(self):
# 对于类方法,会默认传入一个self,表示实例对象,也就是说decorator(func)(self),这一点可以使用下面的decorator 验证。
start_time = time.time()
func(self)
print(time.time() - start_time)
return wapper
class MyObj(object):
def __init__(self, content):
self.content = content
@decorator
def run(self):
time.sleep(0.5)
print(self.content)
# __call__() 把对象转为可执行
def __call__(self, *args, **kwargs):
print('call-------------')
if __name__ == '__main__':
obj = MyObj('你好')
obj.run()
类装饰器
import time
class Decoretor(object):
def __init__(self, func):
print('Decoretor---------')
self.func = func
# __call__()是一个特殊方法,它可将一个类实例变成一个可调用对象
def __call__(self, *args, **kwargs):
start_time = time.time()
self.func()
print('运行时间:', time.time() - start_time)
@Decoretor
def func():
time.sleep(0.5)
print('test--------')
func()
运行结果:
Decoretor---------
test--------
运行时间: 0.5007145404815674
虽然没有创建对象,依然执行了__init__
方法,即Decoretor
被调用
被装饰的函数有不定长参数
from time import ctime, sleep
def timefun(func):
def wrapped_func(*args, **kwargs):
print("%s called at %s"%(func.__name__, ctime()))
func(*args, **kwargs)
return wrapped_func
@timefun
def foo(a, b):
print(a+b)
if __name__ == '__main__':
foo(3,5)