Python中的装饰器

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)))
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在stackoverflow上看到一篇讲python中decorator的回答,实在是受益匪浅,决定将其翻译成中文...
    大蟒传奇阅读 2,901评论 7 31
  • 装饰器 装饰器应用广泛,其特点是可在具体函数执行之前或者之后做相关操作。 比如 执行前打印执行函数的相关信息,对函...
    夏威夷的芒果阅读 276评论 0 0
  • python中的装饰器 函数核心回顾 1.函数是Python中的一等公民,函数也是对象。可以把函数赋值给变量。 2...
    _咚咚咚东阅读 79评论 0 0
  • 姓名:乐仁华 学号:16140220023 转载自: 【嵌牛导读】:本文主要是介绍python中装饰器的...
    小乐杂货铺阅读 442评论 0 0
  • 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,...
    chen_000阅读 1,373评论 0 3