• 【摘】人生苦短,每日python


    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高级编程》

  • 相关阅读:
    获取父子栏目内容的知识点总结:更多信息页面的信息内容获取
    获取栏目内容的知识点总结:SingleInfoSortPortlet类型笔记(单栏目的获取)
    JBPM插件安装(MyEclipse8.5测试成功)和配置
    获取栏目内容的知识点总结:KnobInfoSortPortlet类型笔记(没有层级关系的栏目信息)
    HTML的事件说明
    正交投影、格拉姆施密特正交(一)
    子级Repeater获取父级Repeater绑定项的值
    启用IIS6的Gzip压缩功能
    属性IsLocked不可用于登录"[sa]解决办法
    在IE流览器中正确显示PNG透明图片
  • 原文地址:https://www.cnblogs.com/featherw/p/10311094.html
Copyright © 2020-2023  润新知