【问题标题】:decorator in python 2 that decorate given method of given classpython 2中的装饰器,用于装饰给定类的给定方法
【发布时间】:2021-09-12 16:11:45
【问题描述】:

我已经给出了带有方法m 的任意类A,我想创建可以添加到新函数f 的装饰器,并且这个装饰器将允许每次m 执行f调用但在mf 之前执行f 应该拦截m 的参数

我需要帮助定义 pre_execution 装饰器 - 我有一些东西,但它不工作,我不知道如何让它工作

#a.py
class A:
    def m(self, x):
        return x+1

#mydecorator.py     -- need help with code in this file
def pre_execution(klass, method):
    old_fn = getattr(klass, method)

    def inner(fn, *args):
        # @wraps(fn)
        def iin(*args, **kwargs):
            fn(*args, **kwargs)
            return old_fn(*args, **kwargs)
        return iin
    setattr(klass, method, inner)
    return inner


# main.py
from a import A
from mydecorator import pre_execution

if __name__ == "__main__":
    @pre_execution(A, 'm')
    def f(*args, **kwargs):
        print "in"
        print "my code using args and kwargs"
        print "out"

    a = A()
    print a.m(1) == 2
    print a.m(1)

预期输出:

in
my code using args and kwargs
out
True

【问题讨论】:

  • 装饰f 仅包装对f 的调用。如果你想改变m 的行为,你必须在f 的装饰器中对其进行猴子补丁。
  • 您的预期输出不应该调用f 两次(每次调用a.m 一次)吗?还是只希望f 在创建a 时执行?
  • 真正的问题是什么?
  • @chepner 谢谢你的评论 - 我已经对问题进行了更正

标签: python class decorator python-2.x


【解决方案1】:

我想你想要的是

def pre_execution(klass, method):
    old_method = getattr(klass, method)

    def patch_klass(f):
        def new_method(*args, **kwargs):
            f(*args, **kwargs)
            return old_method(*args, **kwargs)
        setattr(klass, method, new_method)
        return f
    return patch_klass

pre_execution 保存对原始方法的引用,然后定义将返回并在f 上调用的函数。此函数定义了一个 new 方法,该方法在调用原始方法之前调用 fpatch_klass 然后将旧方法替换为新方法。它还会返回未修改的原始函数,以防您想在其他地方使用 f

$ python tmp.py
in
my code using args and kwargs
out
True
in
my code using args and kwargs
out
2

请注意,这适用于 Python 2 或 3。

【讨论】:

    猜你喜欢
    • 2012-02-09
    • 2013-03-10
    • 2020-01-11
    • 2014-01-14
    • 2017-11-12
    • 2011-08-20
    • 1970-01-01
    • 2018-07-14
    相关资源
    最近更新 更多