python2猴子补丁不可能在所有数据类型上都实现,为什么?

2024-04-26 06:36:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近不得不在Python2中使用我不喜欢的hack,并且一直在想-原因是什么-为什么不是每个对象都可以被猴子修补,如下面的例子(粗糙,不检查错误,但这只是为了演示):

import requests

def get_page():
    req = requests.get("https://stackoverflow.com")
    if req.status_code == 200:
        yield req

def prepare_some_content_in_file(file_):
    with open(file_, 'w') as _file:
        _file.write("a texty text")

def patch_file_type():
    """ WILL FAIL ! """

    file_ = "/tmp/some_so_random_name"
    prepare_some_content_in_file(file_)
    with open(file_, 'r') as _file:
        setattr(_file, "text", _file.read())
        yield _file

def patch_func_type():
    """ GO AHEAD """

    file_ = "/tmp/some_so_random_name"
    prepare_some_content_in_file(file_)
    pseudo_file = lambda: None
    with open(file_, 'r') as _file:
        setattr(pseudo_file, "text", _file.read())
        yield pseudo_file

print(get_page())
try:
    for i in patch_file_type():
        print(type(i), i, i.text)
except AttributeError as error:
    print(error)
try:
    for i in patch_func_type():
        print(type(i), i, i.text)
except AttributeError as error:
    print(error)

这只与Python2有关,在Python3中它起作用:

Py2输出:

<generator object get_page at 0x7f8afa7143c0>
'file' object has no attribute 'text'
(<type 'function'>, <function <lambda> at 0x7f8afa456668>, u'a texty text')

Py3输出:

<generator object get_page at 0x7f5c37842570>
<class '_io.TextIOWrapper'> <_io.TextIOWrapper name='/tmp/some_so_random_name' mode='r' encoding='UTF-8'> a texty text
<class 'function'> <function patch_func_type.<locals>.<lambda> at 0x7f5c35a02048> a texty text

这个存在的原因很明显是为了有备用的缓存文件,我可以用和请求对象相同的方式对其进行操作,比如调用文本属性,等等

编辑:回应评论:

dir(_file)
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']


dir(pseudo_file) # lambda acutally
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

它们都没有属性__slots__,这在示例中针对class进行了讨论。我看看那里有没有什么可以用类似的方法处理的。你知道吗


Tags: textnameingetdefastypepage