首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将装饰器附加到python中的“事后”函数?

如何将装饰器附加到python中的“事后”函数?
EN

Stack Overflow用户
提问于 2015-11-23 18:35:14
回答 1查看 6.7K关注 0票数 25

我理解python中函数的装饰符的方式(我可能错了)是,它们应该添加副作用并修改函数的返回值。现在,装饰器被添加到要装饰的函数的函数定义之上,或者通过赋值添加。下面是一个小示例:

代码语言:javascript
复制
def print_args_decor(function):
    def wrapper(*args, **kwargs):
        print 'Arguments:', args, kwargs         # Added side-effect
        return function(*args, **kwargs)*5       # Modified return value
    return wrapper

@print_args_decor
def do_stuff(strg, n=10):
    """Repeats strg a few times."""
    return strg * n

new_decorated_func = print_args_decor(do_stuff)  # Decoration by assignment

print do_stuff('a', 2) # Output: aaaaaaaaaa

现在,如何将装饰器附加到在其他地方定义的函数,理想情况下是保留原始函数的名称和文档字符串(就像functools.wraps一样)?例如,我正在从Python的数学模块导入sqrt()函数,并且想要修饰它,我该怎么做呢?

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

def print_args_decor(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print 'Arguments:', args, kwargs         # Added side-effect
        return function(*args, **kwargs)*5       # Modified return value
    return wrapper

# Decorate the sqrt() function from math module somehow
@print_args_decor #???
sqrt #???

print sqrt(9)   
# Output: 
# Arguments: ([9],) {}
# 15                   # <--- sqrt(9)*5

事后在类中修饰方法如何?装饰类本身怎么样?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-23 18:37:44

您已将sqrt导入到模块中,只需在您自己的全局名称空间中应用装饰器:

代码语言:javascript
复制
sqrt = print_args_decor(sqrt)

这会将模块名称空间中的名称sqrt设置为装饰器的结果。不要求sqrt最初是在此模块中定义的。

由装饰者决定是否使用functools.wraps()装饰器来保存函数元数据,如名称和文档字符串。

装饰类在这方面没有什么不同:

代码语言:javascript
复制
ClassName = decorator(ClassName)

在Python2中,对于方法,需要注意获取原始的未绑定函数;最简单的方法是使用method.__func__属性:

代码语言:javascript
复制
try:
    # Python 2
    ClassName.function_name = decorator(ClassName.function_name.__func__)
except AttributeError:
    # Python 3
    ClassName.function_name = decorator(ClassName.function_name)

我已经将上面的内容包装在一个try...except中,以使该模式能够跨Python版本工作。另一种方法是从类__dict__中获取函数对象,以避免描述符协议的影响:

代码语言:javascript
复制
ClassName.function_name = decorator(ClassName.__dict__['function_name'])
票数 30
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33868886

复制
相关文章

相似问题

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