python和它的装饰器

即使你没听过装饰器,你也一定知道@staticmethod

作为函数的装饰器,你可以这样写

def mydecorator(function):

    def wrapped(*args, **kwargs):

        # 在调用原始函数之前, 做点什么
result = function(*args, **kwargs)
# 在函数调用之后, 做点什么
# 并返回结果
return result
# 返回warpper作为装饰函数
return wrapped

作为一个例子,我写了个非常随意的

def print_hello(function):

    def hello(*args, **kwargs):

        print('hello start')
result = function(*args, **kwargs)
print('hello end')
return 'hello %s' % result
return hello @print_hello
def print_world(): print('world print')
return 'world result' if __name__ == '__main__': print(print_world())

它的结果是

hello start
world print
hello end
hello world result

作为类的装饰器,你可以这样写

class DecoratorAsClass(object):

    def __init__(self, function):

        self.funciton = function

    def __call__(self, *args, **kwargs):

        # 在调用原始函数之前, 做点什么
result = self.funciton(*args, **kwargs)
# 在调用函数之后, 做点什么
# 并返回结果
return result

作为一个例子,我依旧写了一个很随意的

class PrintWrappedClass(object):

    def __init__(self, function):

        self.function = function

    def __call__(self, *args, **kwargs):

        print('wrapped start')
result = self.function(*args, **kwargs)
print('wrapped end')
return result @PrintWrappedClass
class PrintWorld (object): def print_world(self): print('world print')
return 'world result' def print_kitty(self): print('kitty print')
return 'kitty result' if __name__ == '__main__':
print(PrintWorld().print_world())
print('___')
print(PrintWorld().print_kitty())

它的结果是

wrapped start
wrapped end
world print
world result
___
wrapped start
wrapped end
kitty print
kitty result

当然,装饰器也可以传参

def repeat(number=3):

    def actual_decorator(function):

        def wrapper(*args, **kwargs):

            result = None
for _ in range(number):
result = function(*args, **kwargs)
return result
return wrapper
return actual_decorator @repeat(2)
def print_kitty(): print('kitty print')
return 'kitty result' if __name__ == '__main__': print(print_kitty())

它的结果是

kitty print
kitty print
kitty result

然后我想了想,为什么不像函数装饰器的模板那么写呢?

于是,我就随意地写了个错误的例子

def error_repeat(function, number=3):

    def wrapper(*args, **kwargs):

        result = None
for _ in range(number):
result = function(*args, **kwargs)
return result
return wrapper @error_repeat
def print_world(): print('world print')
return 'world result'

它的结果是

world print
world print
world print
world result

很完美,但是当我想传参数进去的时候,犯难了

呃,就姑且将这个错误的示例当做个笑话看看吧

保存内省的装饰器

from functools import wraps

def preserving_decorator(function):

    @wraps(function)
def wrapped(*args, **kwargs): # 包装函数内部文档
return function(*args, **kwargs)
return wrapped

说实话,我没看懂这段

所以摘录下书中的原话

使用装饰器的常见错误是在使用装饰器时不保存函数元数据(主要是文档字符串和原始函数名)。

前面所有示例都存在这个问题。

装饰器组合创建了一个新函数,并返回一个新对象,但却完全没有考虑原始函数的标识。这将使得调试这样装饰过的函数更加困难,也会破坏可能用到的大多数自动生成文档的工具,因为无法访问原始的文档字符串和函数签名。

摘自 《Python高级编程》

最新文章

  1. PHP 扩展开发(将自己的一些代码封装成PHP扩展函数)
  2. Apple、Google、Microsoft的用户体验设计原则
  3. Myeclipse安装SVN插件(转)
  4. C 中读取键盘码
  5. Roll A Ball
  6. CodeForces 628B New Skateboard
  7. OLAP的一些知识——接下去的项目需要的背景
  8. java hashtable
  9. 单选按钮,通过js判断是否选中
  10. Kivy A to Z -- 怎样从python代码中直接訪问Android的Service
  11. Python 文件I/O (转)
  12. hadoop搭建开发环境及编写Hello World
  13. Android----paint触摸轨迹监听
  14. PHP秒杀系统全方位设计(一)
  15. DDoS的类型及原理
  16. Nginx与PHP-FPM运行原理详解
  17. 转载 usb_alloc_coherent 和 usb_free_coherent
  18. [iOS]改变UIAlertController的标题、内容的字体和颜色
  19. LA3510 Pixel Shuffle
  20. skipper http router 简单试用

热门文章

  1. SwiftUI笔记
  2. 对 Flutter 的一些看法
  3. [转载] MATLAB | RGB image representation
  4. 网络-6 IPV6(上)
  5. 【NPDP专项练习】第七章 产品生命周期管理
  6. FileStream与StreamReader区别
  7. C与C++字符串比较
  8. abap screen页签开发注意事项
  9. managing projects with GNU make pdf
  10. Visual C++ Redistributable for Visual Studio各版本下载地址