|  | 
|  | 1 | +# _*_ coding: utf-8 _*_ | 
|  | 2 | + | 
|  | 3 | +""" | 
|  | 4 | +python_decorator.py by xianhu | 
|  | 5 | +""" | 
|  | 6 | + | 
|  | 7 | +import functools | 
|  | 8 | + | 
|  | 9 | + | 
|  | 10 | +# 构建不太参数的装饰器 | 
|  | 11 | +def logging(func): | 
|  | 12 | + @functools.wraps(func) | 
|  | 13 | + def decorator(*args, **kwargs): | 
|  | 14 | + print("%s called" % func.__name__) | 
|  | 15 | + result = func(*args, **kwargs) | 
|  | 16 | + print("%s end" % func.__name__) | 
|  | 17 | + return result | 
|  | 18 | + return decorator | 
|  | 19 | + | 
|  | 20 | + | 
|  | 21 | +# 使用装饰器 | 
|  | 22 | +@logging | 
|  | 23 | +def test01(a, b): | 
|  | 24 | + print("in function test01, a=%s, b=%s" % (a, b)) | 
|  | 25 | + return 1 | 
|  | 26 | + | 
|  | 27 | + | 
|  | 28 | +# 使用装饰器 | 
|  | 29 | +@logging | 
|  | 30 | +def test02(a, b, c=1): | 
|  | 31 | + print("in function test02, a=%s, b=%s, c=%s" % (a, b, c)) | 
|  | 32 | + return 1 | 
|  | 33 | + | 
|  | 34 | + | 
|  | 35 | +# 构建带参数的装饰器 | 
|  | 36 | +def params_chack(*types, **kwtypes): | 
|  | 37 | + def _outer(func): | 
|  | 38 | + @functools.wraps(func) | 
|  | 39 | + def _inner(*args, **kwargs): | 
|  | 40 | + result = [isinstance(_param, _type) for _param, _type in zip(args, types)] | 
|  | 41 | + assert all(result), "params_chack: invalid parameters" | 
|  | 42 | + result = [isinstance(kwargs[_param], kwtypes[_param]) for _param in kwargs if _param in kwtypes] | 
|  | 43 | + assert all(result), "params_chack: invalid parameters" | 
|  | 44 | + return func(*args, **kwargs) | 
|  | 45 | + return _inner | 
|  | 46 | + return _outer | 
|  | 47 | + | 
|  | 48 | + | 
|  | 49 | +# 使用装饰器 | 
|  | 50 | +@params_chack(int, (list, tuple)) | 
|  | 51 | +def test03(a, b): | 
|  | 52 | + print("in function test03, a=%s, b=%s" % (a, b)) | 
|  | 53 | + return 1 | 
|  | 54 | + | 
|  | 55 | + | 
|  | 56 | +# 使用装饰器 | 
|  | 57 | +@params_chack(int, str, c=(int, str)) | 
|  | 58 | +def test04(a, b, c): | 
|  | 59 | + print("in function test04, a=%s, b=%s, c=%s" % (a, b, c)) | 
|  | 60 | + return 1 | 
|  | 61 | + | 
|  | 62 | + | 
|  | 63 | +# 在类的成员方法中使用装饰器 | 
|  | 64 | +class ATest(object): | 
|  | 65 | + @params_chack(object, int, str) | 
|  | 66 | + def test(self, a, b): | 
|  | 67 | + print("in function test of ATest, a=%s, b=%s" % (a, b)) | 
|  | 68 | + return 1 | 
|  | 69 | + | 
|  | 70 | + | 
|  | 71 | +# 同时使用多个装饰器 | 
|  | 72 | +@logging | 
|  | 73 | +@params_chack(int, str, (list, tuple)) | 
|  | 74 | +def test05(a, b, c): | 
|  | 75 | + print("in function test05, a=%s, b=%s, c=%s" % (a, b, c)) | 
|  | 76 | + return 1 | 
|  | 77 | + | 
|  | 78 | + | 
|  | 79 | +# 构建不带参数的装饰器类 | 
|  | 80 | +class Decorator(object): | 
|  | 81 | + | 
|  | 82 | + def __init__(self, func): | 
|  | 83 | + self.func = func | 
|  | 84 | + return | 
|  | 85 | + | 
|  | 86 | + def __call__(self, *args, **kwargs): | 
|  | 87 | + print("%s called" % self.func.__name__) | 
|  | 88 | + result = self.func(*args, **kwargs) | 
|  | 89 | + print("%s end" % self.func.__name__) | 
|  | 90 | + return result | 
|  | 91 | + | 
|  | 92 | + | 
|  | 93 | +# 使用装饰器 | 
|  | 94 | +@Decorator | 
|  | 95 | +def test06(a, b, c): | 
|  | 96 | + print("in function test06, a=%s, b=%s, c=%s" % (a, b, c)) | 
|  | 97 | + return 1 | 
|  | 98 | + | 
|  | 99 | + | 
|  | 100 | +# 构建带参数的装饰器类 | 
|  | 101 | +class ParamCheck(object): | 
|  | 102 | + | 
|  | 103 | + def __init__(self, *types, **kwtypes): | 
|  | 104 | + self.types = types | 
|  | 105 | + self.kwtypes = kwtypes | 
|  | 106 | + return | 
|  | 107 | + | 
|  | 108 | + def __call__(self, func): | 
|  | 109 | + @functools.wraps(func) | 
|  | 110 | + def _inner(*args, **kwargs): | 
|  | 111 | + result = [isinstance(_param, _type) for _param, _type in zip(args, self.types)] | 
|  | 112 | + assert all(result), "params_chack: invalid parameters" | 
|  | 113 | + result = [isinstance(kwargs[_param], self.kwtypes[_param]) for _param in kwargs if _param in self.kwtypes] | 
|  | 114 | + assert all(result), "params_chack: invalid parameters" | 
|  | 115 | + return func(*args, **kwargs) | 
|  | 116 | + return _inner | 
|  | 117 | + | 
|  | 118 | + | 
|  | 119 | +# 使用装饰器 | 
|  | 120 | +@ParamCheck(int, str, (list, tuple)) | 
|  | 121 | +def test07(a, b, c): | 
|  | 122 | + print("in function test06, a=%s, b=%s, c=%s" % (a, b, c)) | 
|  | 123 | + return 1 | 
|  | 124 | + | 
|  | 125 | + | 
|  | 126 | +# 装饰器实例: 函数缓存 | 
|  | 127 | +def funccache(func): | 
|  | 128 | + cache = {} | 
|  | 129 | + | 
|  | 130 | + @functools.wraps(func) | 
|  | 131 | + def _inner(*args): | 
|  | 132 | + if args not in cache: | 
|  | 133 | + cache[args] = func(*args) | 
|  | 134 | + return cache[args] | 
|  | 135 | + return _inner | 
|  | 136 | + | 
|  | 137 | + | 
|  | 138 | +# 使用装饰器 | 
|  | 139 | +@funccache | 
|  | 140 | +def test08(a, b, c): | 
|  | 141 | + # 其他复杂或耗时计算 | 
|  | 142 | + return a + b + c | 
|  | 143 | + | 
|  | 144 | + | 
|  | 145 | +# 使用Python自带的装饰器 | 
|  | 146 | +class People(object): | 
|  | 147 | + | 
|  | 148 | + def __init__(self): | 
|  | 149 | + self._name = None | 
|  | 150 | + self._age = None | 
|  | 151 | + return | 
|  | 152 | + | 
|  | 153 | + @property | 
|  | 154 | + def name(self): | 
|  | 155 | + return self._name | 
|  | 156 | + | 
|  | 157 | + @name.setter | 
|  | 158 | + def name(self, name): | 
|  | 159 | + self._name = name | 
|  | 160 | + return | 
|  | 161 | + | 
|  | 162 | + @property | 
|  | 163 | + def age(self): | 
|  | 164 | + return self._age | 
|  | 165 | + | 
|  | 166 | + @age.setter | 
|  | 167 | + def age(self, age): | 
|  | 168 | + assert 0 < age < 120 | 
|  | 169 | + self._age = age | 
|  | 170 | + return | 
|  | 171 | + | 
|  | 172 | + | 
|  | 173 | +# 类静态方法和类方法 | 
|  | 174 | +class A(object): | 
|  | 175 | + var = 1 | 
|  | 176 | + | 
|  | 177 | + def func(self): | 
|  | 178 | + print(self.var) | 
|  | 179 | + return | 
|  | 180 | + | 
|  | 181 | + @staticmethod | 
|  | 182 | + def static_func(): | 
|  | 183 | + print(A.var) | 
|  | 184 | + return | 
|  | 185 | + | 
|  | 186 | + @classmethod | 
|  | 187 | + def class_func(cls): | 
|  | 188 | + print(cls.var) | 
|  | 189 | + cls().func() | 
|  | 190 | + return | 
0 commit comments