gpt4 book ai didi

python - 如何使用另一个类的方法装饰(monkeypatch...)Python 类?

转载 作者:行者123 更新时间:2023-11-30 23:54:32 25 4
gpt4 key购买 nike

两者httplib.HTTPMessageemail.message.Message classes[1] 实现了 RFC822 header 解析的方法。不幸的是,它们有不同的实现[2],并且不提供相同级别的功能。

困扰我的一个例子是:

  • httplib.HTTPMessage缺少 get_filename email.Message中存在的方法,这使您可以轻松地从 Content-disposition: attachment; filename="fghi.xyz" 检索文件名 header ;

  • httplib.HTTPMessagegetparam , getplistparseplist方法,但据我所知,它们不是也不能在 content-type 之外使用头部解析;

  • email.Message有一个通用的get_param方法来解析带有参数的任何 RFC822 header ,例如 content-dispositioncontent-type .

因此,我想要 get_filenameget_param email.message.Message的方法在httplib.HTTPMessage但是,当然,我无法修补 httplib.HTTPMessage因为它在标准库中......:-q

最后,装饰器主题来了......:-)

我成功创建了monkeypatch_http_message装饰 httplib.HTTPMessage 的功能我缺少的解析方法:

def monkeypatch_http_message(obj):
from email import utils
from email.message import (
_parseparam,
_unquotevalue,
)
cls = obj.__class__

# methods **copied** from email.message.Message source code
def _get_params_preserve(self, failobj, header): ...
def get_params(self, failobj=None, header='content-type',
unquote=True): ...
def get_param(self, param, failobj=None, header='content-type',
unquote=True): ...
def get_filename(self, failobj=None): ...

# monkeypatching httplib.Message
cls._get_params_preserve = _get_params_preserve
cls.get_params = get_params
cls.get_param = get_param
cls.get_filename = get_filename

现在我可以做:

import mechanize
from some.module import monkeypatch_http_message
browser = mechanize.Browser()

# in that form, browser.retrieve returns a temporary filename
# and an httplib.HTTPMessage instance
(tmp_filename, headers) = browser.retrieve(someurl)

# monkeypatch the httplib.HTTPMessage instance
monkeypatch_http_message(headers)

# yeah... my original filename, finally
filename = headers.get_filename()

这里的问题是我从字面上复制了源类中的装饰方法代码,我想避免这种情况。

因此,我尝试通过引用源方法进行装饰:

def monkeypatch_http_message(obj):
from email import utils
from email.message import (
_parseparam,
_unquotevalue,
Message # XXX added
)
cls = obj.__class__

# monkeypatching httplib.Message
cls._get_params_preserve = Message._get_params_preserve
cls.get_params = Message.get_params
cls.get_param = Message.get_param
cls.get_filename = Message.get_filename

但这给了我:

Traceback (most recent call last):
File "client.py", line 224, in <module>
filename = headers.get_filename()
TypeError: unbound method get_filename() must be called with Message instance as first argument (got nothing instead)

我现在正在摸不着头脑...如何在不直接复制源方法的情况下装饰我的类?

有什么建议吗? :-)

问候,

乔治·马丁

<小时/>
  1. 在 Python 2.6 中。我无法在生产中使用 2.7 或 3.x。

  2. httplib.HTTPMessage继承自mimetools.Messagerfc822.Messageemail.Message有自己的实现。

最佳答案

在 Python 3.x 中,未绑定(bind)的方法消失了,因此在这种情况下您将只获取文件对象,并且您的第二个示例将起作用:

>>> class C():
... def demo(): pass
...
>>> C.demo
<function demo at 0x1fed6d8>

在 Python 2.x 中,您可以通过未绑定(bind)方法访问底层函数,也可以直接从类字典中检索它(从而绕过将其转换为未绑定(bind)方法的正常查找过程):

>>> class C():
... def demo(): pass
...
>>> C.demo.im_func # Retrieve it from the unbound method
<function demo at 0x7f463486d5f0>
>>> C.__dict__["demo"] # Retrieve it directly from the class dict
<function demo at 0x7f463486d5f0>

后一种方法的优点是向前兼容 Python 3.x。

关于python - 如何使用另一个类的方法装饰(monkeypatch...)Python 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5106356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com