首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保留签名和用户定义属性的Python装饰器

保留签名和用户定义属性的Python装饰器
EN

Stack Overflow用户
提问于 2018-02-12 20:31:19
回答 4查看 1.8K关注 0票数 9

我有一个装饰my_func的简单装饰器my_decorator

代码语言:javascript
复制
def my_decorator(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    wrapper._decorator_name_ = 'my_decorator'
    return wrapper

@my_decorator
def my_func(x):
    print('hello %s'%x)

my_func._decorator_name_
'my_decorator'

在此之前,一切正常,但我看不到函数的实际签名。

代码语言:javascript
复制
my_func?
Signature: my_func(*args, **kwargs)
Docstring: <no docstring>
File:      ~/<ipython-input-2-e4c91999ef66>
Type:      function

如果我用python的decorator.decorator装饰我的装饰器,我可以看到我的函数的签名,但是我不能拥有我定义的新属性。

代码语言:javascript
复制
import decorator

@decorator.decorator
def my_decorator(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    wrapper._decorator_name_ = 'my_decorator'
    return wrapper

@my_decorator
def my_func(x):
    print('hello %s'%x)

my_func?
Signature: my_func(x)
Docstring: <no docstring>
File:      ~/<ipython-input-8-934f46134434>
Type:      function

my_func._decorator_name_
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-7e3ef4ebfc8b> in <module>()
----> 1 my_func._decorator_name_

AttributeError: 'function' object has no attribute '_decorator_name_'

在python2.7中怎样才能同时拥有这两个功能呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-02-12 20:48:22

对于Python3,在标准库中使用functools.wraps

代码语言:javascript
复制
from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    wrapper._decorator_name_ = 'my_decorator'
    return wrapper

@my_decorator
def my_func(x):
    print('hello %s'%x)

print(my_func._decorator_name_)
票数 12
EN

Stack Overflow用户

发布于 2018-02-17 04:16:07

@decorator.decorator返回一个函数,该函数接受另一个函数作为输入。在本例中,您需要返回函数上的属性。

要让它在Python 2.7上工作,您只需进行一些调整

代码语言:javascript
复制
import decorator

def my_dec2(func):
    @decorator.decorator
    def my_decorator(func, *args, **kwargs):
        print("this was called")
        return func(*args, **kwargs)

    test = my_decorator(func)
    test._decorator_name_ = "my_decorator"
    return test

@my_dec2
def my_func(x):
    print('hello %s'%x)


my_func(2)
print(my_func._decorator_name_)

然后当你测试它工作的时候

代码语言:javascript
复制
In [1]: my_func?
Signature: my_func(x)
Docstring: <no docstring>
File:      ~/Desktop/payu/projects/decotest/decos.py
Type:      function

In [2]: my_func._decorator_name_
Out[2]: 'my_decorator'
票数 6
EN

Stack Overflow用户

发布于 2018-02-17 08:41:47

如果你想以某种方式改变你的函数的行为,你只需要定义一个wrapper函数。因此,如果你真的只想在不改变函数行为的情况下向函数添加一些属性,你可以简单地执行以下操作。

代码语言:javascript
复制
def my_decorator(func):
    func._decorator_name_ = 'my_decorator'
    return func

在更复杂的情况下,你需要一个wrapper,我建议遵循accepted answer for this question,它解释了如何创建一个行为与另一个相同的函数,但具有自定义的签名。使用inspect.getargspec,您可以从my_func恢复签名,并将其转置到您的wrapper

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48746567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档