如何理解python装饰器
闭包

装饰器(decorator)
def yanzheng(func): def inner(): print("正在验证1 2 3") func() print("执行完成") return inner # 使用装饰器的形式 @装饰器函数 @yanzheng def f1(): print("in f1") """上面三行的代码等价于 def f1(): print("这是一个底层的函数") f1 = yanzheng(f1) """ # f1已经不是原来的f1了 而是一个被装饰之后的f1 f1() @yanzheng def f2(): print("in f2") f2() """装饰器函数的特点 符合闭包的基本形式 有一个函数参数是被装饰的函数的引用"""
有参数和有范围值的装饰器
import time def gettime(func): def inner(*args, **kwargs): # 将收到数据的打包 位置参数和关键字参数 begin = time.time() # 将被装饰的函数返回值暂存 ret = func(*args, **kwargs) # 将收到的参数拆包为收到的样子 end = time.time() print("函数花费%f" % (end-begin)) return ret return inner @gettime def f1(): print("in f1") for i in range(1): time.sleep(1) @gettime def f2(number2): # f2 = gettime(f2) print("number2 = %d" % number2) time.sleep(0.2) print("in f2") return 100 f1() print("函数的返回值是%s" % f2(100))
装饰器工厂
import time # 产生装饰器函数的函数就是装饰器工厂 # 目的:通过给装饰器工厂函数传递参数 控制内部函数的行为 def get_run_time(flag): def gettime(func): def inner(*args, **kwargs): # 将收到数据的打包 begin = time.time() # 将被装饰的函数返回值暂存 ret = func(*args, **kwargs) # 将收到的参数拆包为收到的样子 end = time.time() if flag == 'int': print("函数花费%d s" % int(end - begin)) else: print("函数花费%f s" % (end-begin)) return ret return inner return gettime @get_run_time("int") def f1(): print("in f1") for i in range(1): time.sleep(1) f1()

类装饰器
装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 __call__() 方法,那么这个对象就是callable的。
class Test(object): def __init__(self, func): print("---初始化---") print("func name is %s"%func.__name__) self.__func = func def __call__(self): print("---装饰器中的功能---") self.__func() #说明: #1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象 # 并且会把test这个函数名当做参数传递到__init__方法中 # 即在__init__方法中的属性__func指向了test指向的函数 # #2. test指向了用Test创建出来的实例对象 # #3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法 # #4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用 # 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体 @Test def test(): print("----test---") test() showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"
运行结果如下:
---初始化--- func name is test ---装饰器中的功能--- ----test---
多重装饰器
def makeBold(fn): def wrapped(): return "<b>" + fn() + "</b>" return wrapped def makeItalic(fn): def wrapped(): return "<i>" + fn() + "</i>" return wrapped # f1 = makeBold(f1) @makeBold @makeItalic def f1(): return "hello" @makeItalic @makeBold def f2(): #先靠近f2的装饰器先执行 return "python" print(f1()) print(f2())
运行结果:
<b><i>hello</i></b> <i><b>python</b></i>
浙公网安备 33010602011771号