首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python装饰器如何更改修饰函数中的调用?

python装饰器如何更改修饰函数中的调用?
EN

Stack Overflow用户
提问于 2019-10-28 20:05:08
回答 2查看 143关注 0票数 0

我不知道该怎么做,坦率地说,我不知道这是否可能。

我想编写一个修饰器来改变函数的调用方式。用示例代码最容易看到:

代码语言:javascript
复制
def my_print(*args, **kwargs):
    print(args[0].upper())

@reroute_decorator('print', my_print)
def my_func():
    print('normally this print function is just a print function...')
    print('but since my_func is decorated with a special reroute_decorator...')
    print('it is replaced with a different function, and its args sent there.')

my_func()
# NORMALLY THIS PRINT FUNCTION IS JUST A PRINT FUNCTION...
# BUT SINCE MY_FUNC IS DECORATED WITH A SPECIAL REROUTE_DECORATOR...
# IT IS REPLACED WITH A DIFFERENT FUNCTION, AND ITS ARGS SENT THERE.

在python中,具有这种功能的装饰师可能吗?

现在,如果它太复杂的话,我真的不需要它,我只是想不出如何用简单的方法来完成它。

这种问题是微不足道的吗?还是真的很复杂?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-28 20:34:29

要详细说明@Dan D.'s answer,您需要创建一个新的函数对象来替换原始函数,如下所示:

代码语言:javascript
复制
from types import FunctionType

def reroute_decorator(**kwargs):
    def actual_decorator(func):
        globals = func.__globals__.copy()
        globals.update(kwargs)
        new_func = FunctionType(
            func.__code__, globals, name=func.__name__,
            argdefs=func.__defaults__, closure=func.__closure__)
        new_func.__dict__.update(func.__dict__)
        return new_func
    return actual_decorator

这里唯一的问题是,更新后的函数对象是唯一能够看到传入的任何kwargs的对象,因为它们将被欺骗为全局对象。此外,在调用装饰器函数之后对模块所做的任何修改对修饰函数都是不可见的,但这不应该是一个问题。您可以进行更深一层的操作,并创建一个代理字典,该字典允许您正常地与原始密钥交互,除了您显式定义的键(如print )之外,但这超出了这里的范围。

我已经更新了您的print实现,使其更加通用,并使对装饰器函数的输入更加pythonic (少了MATLABy):

代码语言:javascript
复制
def my_print(*args, **kwargs):
    print(*(str(x).upper() for x in args), **kwargs)

@reroute_decorator(print=my_print)
def my_func():
    print('normally this print function is just a print function...')
    print('but since my_func is decorated with a special reroute_decorator...')
    print('it is replaced with a different function, and its args sent there.')

其结果是:

代码语言:javascript
复制
>>> my_func()
NORMALLY THIS PRINT FUNCTION IS JUST A PRINT FUNCTION...
BUT SINCE MY_FUNC IS DECORATED WITH A SPECIAL REROUTE_DECORATOR...
IT IS REPLACED WITH A DIFFERENT FUNCTION, AND ITS ARGS SENT THERE.
票数 1
EN

Stack Overflow用户

发布于 2019-10-28 20:34:44

您可以使用更新的globals字典创建一个新函数,以便将全局函数绑定到所需的值。

注意,这比实际的动态范围要弱,因为函数调用的任何函数都将看到原始绑定,而不是修改后的绑定。

参见在namespaced_function中引用的How does Python's types.FunctionType create dynamic Functions?

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

https://stackoverflow.com/questions/58597680

复制
相关文章

相似问题

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