美文网首页
Python中的装饰器

Python中的装饰器

作者: fisher爱吃鱼 | 来源:发表于2017-12-29 11:07 被阅读37次

    Python中的装饰器

    不带参数的装饰器

    #!coding:utf-8
    
    
    def use_logging(func):
    
        def wrapper(*args, **kwargs):
            print("%s is running" % func.__name__)
            return func(*args)
        return wrapper
    
    
    @use_logging
    def foo():
        print("i am foo")
    
    
    @use_logging
    def bar():
        print("i am bar")
    
    foo()
    bar()
    

    带参数的装饰器

    #!coding:utf-8
    
    
    def use_logging(level):
    
        def decorator(func):
            def wrapper(*args, **kwargs):
                print("[%s]%s is running" % (level, func.__name__))
                return func(*args)
            return wrapper
        return decorator
    
    
    @use_logging(level='error')
    def foo():
        print("i am foo")
    
    
    @use_logging(level='warn')
    def bar():
        print("i am bar")
    
    foo()
    bar()
    

    类装饰器

    #!coding:utf-8
    
    
    class Foo(object):
    
        def __init__(self, func):
            self._func = func
    
        def __call__(self):
            print('class decorator runing')
            self._func()
            print('class decorator ending')
    
    
    @Foo
    def bar():
        print('bar')
    
    bar()
    

    functools.wraps

    使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的 docstring__name__、参数列表,先看例子:

    #!coding:utf-8
    
    
    def logged(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 'with_logging'
    print(f.__doc__)     # prints None
    

    函数 f 等价于:

    def f(x):
        """does some math"""
        return x + x * x
    f = logged(f)
    

    不难发现,函数 fwith_logging 取代了,当然它的 docstring__name__ 就是变成了with_logging函数的信息了。

    这个问题就比较严重的,好在我们有 functools.wrapswraps 本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了。

    from functools import wraps
    
    
    def logged(func):
        @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 math'
    

    内置装饰器

    @staticmathod@classmethod@property

    装饰器的顺序

    @a
    @b
    @c
    def f ():
    

    等效于

    f = a(b(c(f)))

    相关文章

      网友评论

          本文标题:Python中的装饰器

          本文链接:https://www.haomeiwen.com/subject/fuligxtx.html