1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
| # encoding: utf-8 """ -------------------------------------- @describe @version: 1.0 @project: websockets @file: test.py @author: yuanlang @time: 2019-03-18 14:29 --------------------------------------- """
# 先看看函数复制 def a(): pass
print(a) x = a print(x)
# 结论 # a方法地址给了 x # 两个地址都是 a方法 print("---------------------------------------")
def log_track(func): def wapper(*args, **kwargs): print(func.__name__) func(*args, **kwargs)
return wapper
def hello2(): pass
@log_track def hello(): print("hello")
print(hello) hello = wapper = log_track(hello) # 和 @log_track效果一样 print(hello) print(hello2.__name__) print(hello.__name__)
# 结论 # hello指针指向的hello函数地址进入到wapper作用域中,返回的wapper函数地址给 hello print("---------------------------------------")
# 带参数的装饰器 def user_loggin(level): print(level)
def decoration(func): print(func.__name__)
def wrapper(*args,**kwargs): print(func.__name__) func(*args,**kwargs) print("return wrapper") return wrapper print("return decoration") return decoration
def foo(): return "foo"
func = decoration = user_loggin(level="debug") print(func) print("func.__name__ >>>>> ",func.__name__) print("######################") func = wrapper = user_loggin(level="debug")(foo) print(func) print("func.__name__ >>>>>",func.__name__) print("######################")
@user_loggin(level="debug") def foo2(): print("fool") # 总结 # 带参数的装饰器比不带参数的装饰器多一层,需先解压出装饰器 print("---------------------------------------")
# 类装饰器 class Foo():
def __init__(self,func): self.__func=func
def __call__(self, *args, **kwargs): print("before call") self.__func(*args,**kwargs) print("after call") return self.__func
def test(): print("test")
foo_obj=Foo(test) print(foo_obj) print("__call__",foo_obj()) print("######################")
print("__call__",foo_obj.__call__()) print("######################")
@Foo def test1(): print("test1")
test1() # 总结 # 类装饰器 实质是将 类的__call__地址 负值给要装饰的函数 test1=Foo(test1).__call__ print("---------------------------------------")
## ## 可以发现 需要被装饰的函数的 docstring、__name__ 被装饰器替代了 ## 所以引出 functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中 ## from functools import wraps
def logged(func):
#func=decoration=wraps(func)(with_logging) #wraps(func)解压并调用类装饰器 #func=partial().__call__ #update_wapper 将with_loggin 的某些参数负值给f return 的 with_logging 变为 f @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") return func(*args, **kwargs)
return with_logging
@logged def f(x): """does some math""" return x + x * x
print(f.__name__ ) # prints 'f' print(f.__doc__ ) # prints 'does some math1'
|