我想在一个类中装饰一个方法但不编辑class.py——里面有细节

Posted

技术标签:

【中文标题】我想在一个类中装饰一个方法但不编辑class.py——里面有细节【英文标题】:I want to decorate a method in a class but without editing class.py -- details inside 【发布时间】:2012-08-01 23:26:24 【问题描述】:

Twython 模块在内部使用 requests 模块。

我想包装/装饰请求的 requests.post(*k, **kw) 方法,以便 Twython 进行 request.post(...) 调用的所有内容都将被透明地装饰/包装,而不会干扰 Twython 模块。

如果我编辑请求代码库会很容易,但我很好奇如何解决将装饰器添加到已定义函数/方法的一般问题。

import requests
def magic_wrapper_doodad(...)
...
...
requests.post = magic_wrapper_doodad(my_function, requests.post) # plz?

import Twython

# thanks to the above magic, requests.post is wrapped just as if it was defined like:
@decorator
def trace(f, *args, **kw):
    print("calling %s with args %s, %s" % (f.__name__, args, kw))
    return f(*args, **kw)

...
... #inside requests.py now:
@trace
def post(self, *args, **kw):
...

如何编写magic_wrapper_doodad() - 或一些替代代码 - 以便我可以像这样装饰代码?

【问题讨论】:

【参考方案1】:

Martijn Pieters' answer 是如果您需要装饰请求功能的方式。我只是想我会提到请求确实有a mechanism for hooks。

如果您可以使用钩子来做您需要做的事情,那么您应该这样做。它比猴子补丁更干净。

【讨论】:

我知道钩子,有几个不同的原因我想装饰request 调用,其中之一是自动向请求添加钩子。如果不装饰 request.get/request.post 方法或修改 Twython 的代码,理想情况下如何做到这一点?【参考方案2】:

装饰器@ 表示法只是语法糖,用于调用装饰器可调用装饰器并用结果替换装饰器。

换句话说,以下两个例子是完全一样的:

@yourdecorator
def a_function():
    pass

def b_function():
    pass
b_function = yourdecorator(b_function)

这同样适用于类定义中的方法。

因此,您可以通过将类方法替换为可调用装饰器的结果来简单地装饰类方法:

requests.post = my_function(requests.post)

这和你写的一样:

class requests(object):
    @my_function
    def post(self, *args):
        pass

请注意,在您的情况下,requests 实际上是一个模块,而不是一个类,但适用相同的原则。

【讨论】:

@jterrace: s 正确插入字符。 requests 是一个模块,而不是一个类。 +1 @jterrace:是的,OP 的问题措辞表明 他/她 认为这是一个类;我正在添加模块注释。 是的,这是非常确定的,但是......该函数没有出现包装。我的实际代码不像 twython/requests 示例那么简单,但我认为它在功能上是等效的,显然我在某处发生了一些可疑的事情,这与我认为的日志/输出有关。 如果您在获得对 unwrapped 函数的引用后进行包装,则不会自动为您包装该引用。例如,尝试在导入 Twyton之前导入请求。【参考方案3】:

您正在寻找的可能是面向方面的编程。

查看 *** 上的这篇文章,如果有帮助请告诉我:

Do you use AOP (Aspect Oriented Programming) in production software?

【讨论】:

以上是关于我想在一个类中装饰一个方法但不编辑class.py——里面有细节的主要内容,如果未能解决你的问题,请参考以下文章

在 MRO 中装饰顶部功能

如何在 android 中装饰编辑文本? [关闭]

在类中装饰 @property.setter 装饰器 [重复]

在 Python 中装饰方法签名中没有 self 的类

python中装饰器装饰类中的方法

是否可以在 Typescript 中装饰装饰器?