【问题标题】:Overriding the arguments sent to python decorator of an instance method覆盖发送给实例方法的python装饰器的参数
【发布时间】:2020-01-07 10:01:47
【问题描述】:

我在一个类中有一个方法,该方法用带参数的装饰器进行装饰。像这样的:

class SomeClass():
    @dec(arg1, arg2, arg3)
    def some_func(farg1, farg2, farg3):
        ....
        ...

装饰器是这样的

def dec(*data):
    def _api(func):
        func.__arguments_sent__ = data

        def internal_func(func, *args, **kwargs):
            response = func(*args, **kwargs)
            return response

        return decorator.decorator(internal_fun, func)
    return _api

我正在尝试修改“SomeClass”的某些已创建实例的 arg3(像这样在装饰器中发送 - @dec(arg1, arg2, arg3))。如何在不更改源代码并重新创建此实例的情况下实现此目的?

我有一个可以修改这个实例的后门进程。我正在寻找实现此修改的最简单方法。

【问题讨论】:

  • 您能否提供一个示例来说明如何调用它以及会发生什么。 arg3 会是 SomeClass 被更改的属性的名称吗?您如何确定将其更改为的值?
  • @PatrickHaugh:我在传递给装饰器的参数和函数之间进行了一些映射。我的装饰器的定义很长,它检查关系是否成立。 arg3 是一些静态值,例如 '5' 等,与 SomeClass 的动态更改实例无关。简而言之,我的 arg3 在代码中是“5”,我想将其更改为“4”而不重新创建我的实例方法。谢谢。
  • 装饰器参数在解析类时被评估,这比你创建实例要早得多,所以一旦你有了实例就忘了改变它们。您应该从类变量或实例变量中提供该参数,而不是作为装饰器的参数

标签: python overriding decorator


【解决方案1】:

可以修改由闭包绑定的对象,但有一些注意事项:

  1. 您将无法将该引用更改为指向新对象
  2. 类的所有实例共享方法定义,因此它们共享绑定的闭包变量

这是一个例子

import inspect

def deco(**data):
    def outer(func):
        def inner(*args, **kwargs):
            print(data)
            return func(*args, **kwargs)
        return inner
    return outer

class A:
    @deco(a=1, b=2, c=3)
    def f(self):
        pass

a = A()
a.f()  # {'a': 1, 'b': 2, 'c': 3}
b = A()
b.f()  # {'a': 1, 'b': 2, 'c': 3}
inspect.getclosurevars(a.f).nonlocals['data']['a'] = 3
a.f()  # {'a': 3, 'b': 2, 'c': 3}
b.f()  # {'a': 3, 'b': 2, 'c': 3}

对于您实际尝试解决的问题,几乎可以肯定有一个更简洁的解决方案,它不涉及事后修改方法定义。

【讨论】:

    猜你喜欢
    • 2017-07-12
    • 2021-10-04
    • 1970-01-01
    • 2013-02-12
    • 2019-01-03
    • 2019-05-24
    • 2017-11-12
    • 1970-01-01
    相关资源
    最近更新 更多