diff --git a/README.md b/README.md index f92b045..f52b5ee 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # LearnPython 以撸代码的形式学习Python, 具体说明在[知乎专栏-撸代码,学知识](https://zhuanlan.zhihu.com/pythoner) -============================================================ +=============================================================================== ### python_base.py: 千行代码入门Python ### python_visual.py: 15张图入门Matplotlib @@ -19,6 +19,8 @@ ### python_requests.py: Python中最好用的爬虫库Requests代码实例 ### python_functional.py: Python进阶: 函数式编程实例(附代码) -============================================================ + +### python_decorator.py: Python进阶: 通过实例详解装饰器(附代码) +=============================================================================== ### 您可以fork该项目,并在修改后提交Pull request diff --git a/python_decorator.py b/python_decorator.py new file mode 100644 index 0000000..b60a251 --- /dev/null +++ b/python_decorator.py @@ -0,0 +1,190 @@ +# _*_ coding: utf-8 _*_ + +""" +python_decorator.py by xianhu +""" + +import functools + + +# 构建不太参数的装饰器 +def logging(func): + @functools.wraps(func) + def decorator(*args, **kwargs): + print("%s called" % func.__name__) + result = func(*args, **kwargs) + print("%s end" % func.__name__) + return result + return decorator + + +# 使用装饰器 +@logging +def test01(a, b): + print("in function test01, a=%s, b=%s" % (a, b)) + return 1 + + +# 使用装饰器 +@logging +def test02(a, b, c=1): + print("in function test02, a=%s, b=%s, c=%s" % (a, b, c)) + return 1 + + +# 构建带参数的装饰器 +def params_chack(*types, **kwtypes): + def _outer(func): + @functools.wraps(func) + def _inner(*args, **kwargs): + result = [isinstance(_param, _type) for _param, _type in zip(args, types)] + assert all(result), "params_chack: invalid parameters" + result = [isinstance(kwargs[_param], kwtypes[_param]) for _param in kwargs if _param in kwtypes] + assert all(result), "params_chack: invalid parameters" + return func(*args, **kwargs) + return _inner + return _outer + + +# 使用装饰器 +@params_chack(int, (list, tuple)) +def test03(a, b): + print("in function test03, a=%s, b=%s" % (a, b)) + return 1 + + +# 使用装饰器 +@params_chack(int, str, c=(int, str)) +def test04(a, b, c): + print("in function test04, a=%s, b=%s, c=%s" % (a, b, c)) + return 1 + + +# 在类的成员方法中使用装饰器 +class ATest(object): + @params_chack(object, int, str) + def test(self, a, b): + print("in function test of ATest, a=%s, b=%s" % (a, b)) + return 1 + + +# 同时使用多个装饰器 +@logging +@params_chack(int, str, (list, tuple)) +def test05(a, b, c): + print("in function test05, a=%s, b=%s, c=%s" % (a, b, c)) + return 1 + + +# 构建不带参数的装饰器类 +class Decorator(object): + + def __init__(self, func): + self.func = func + return + + def __call__(self, *args, **kwargs): + print("%s called" % self.func.__name__) + result = self.func(*args, **kwargs) + print("%s end" % self.func.__name__) + return result + + +# 使用装饰器 +@Decorator +def test06(a, b, c): + print("in function test06, a=%s, b=%s, c=%s" % (a, b, c)) + return 1 + + +# 构建带参数的装饰器类 +class ParamCheck(object): + + def __init__(self, *types, **kwtypes): + self.types = types + self.kwtypes = kwtypes + return + + def __call__(self, func): + @functools.wraps(func) + def _inner(*args, **kwargs): + result = [isinstance(_param, _type) for _param, _type in zip(args, self.types)] + assert all(result), "params_chack: invalid parameters" + result = [isinstance(kwargs[_param], self.kwtypes[_param]) for _param in kwargs if _param in self.kwtypes] + assert all(result), "params_chack: invalid parameters" + return func(*args, **kwargs) + return _inner + + +# 使用装饰器 +@ParamCheck(int, str, (list, tuple)) +def test07(a, b, c): + print("in function test06, a=%s, b=%s, c=%s" % (a, b, c)) + return 1 + + +# 装饰器实例: 函数缓存 +def funccache(func): + cache = {} + + @functools.wraps(func) + def _inner(*args): + if args not in cache: + cache[args] = func(*args) + return cache[args] + return _inner + + +# 使用装饰器 +@funccache +def test08(a, b, c): + # 其他复杂或耗时计算 + return a + b + c + + +# 使用Python自带的装饰器 +class People(object): + + def __init__(self): + self._name = None + self._age = None + return + + @property + def name(self): + return self._name + + @name.setter + def name(self, name): + self._name = name + return + + @property + def age(self): + return self._age + + @age.setter + def age(self, age): + assert 0 < age < 120 + self._age = age + return + + +# 类静态方法和类方法 +class A(object): + var = 1 + + def func(self): + print(self.var) + return + + @staticmethod + def static_func(): + print(A.var) + return + + @classmethod + def class_func(cls): + print(cls.var) + cls().func() + return