>> class MyDict(dict): ... def __getitem__(s-6ren">
gpt4 book ai didi

python - Monkeypatching 函数命名空间

转载 作者:太空宇宙 更新时间:2023-11-03 10:50:54 24 4
gpt4 key购买 nike

灵感来自 "Define @property on function" ,我试图覆盖函数的命名空间:

>>> class MyDict(dict):
... def __getitem__(self, item):
... if item == 'k2':
... return 'v2'
... return super().__getitem__(item)
...
>>> def f():
... pass
...
...
>>> f.__dict__ = MyDict({'k1': 'v1'})
>>>
>>> f.k1
'v1'
>>> f.k2
AttributeError: 'function' object has no attribute 'k2'

为什么f.k1可以解析,而f.k2不能?

最佳答案

简短版本:因为 CPython 的 PyDict_GetItem 函数不是子类友好的(明确地说,它不是故意的;PyDict_* 函数都是专门用于 PyDict_Object 本身,而不是广义映射)。

长版本:检索属性调用 PyObject_GetAttr。对于没有显式定义自定义 tp_getattrotp_getattr(和 PyFunction_Type does not )的类,这最终是 calling PyObject_GenericGetAttr .假设在类本身上找不到任何东西,PyObject_GenericGetAttr(嗯,实现它的私有(private) API 函数)retrieves __dict__ as normal, then calls PyDict_GetItem to retrieve the value . PyDict_GetItem 显式使用 dict 的 C 级内部机制来执行访问,绕过您可能定义的任何自定义 __getitem__。所以你的自定义 __getitem__ 永远不会被调用;出于所有实际目的,您的 dict 子类只是一个 dict

我最初希望您可能能够通过 the officially supported __missing__ hook 使这个特殊案例有效,但事实证明只有在调用 __getitem__ (dict_subscript) 的等效项时才会调用它,而不是通过像 PyDict_GetItem 这样的 C 级直接访问 API (根本不通过 dict_subscript)。

基本上,CPython 似乎已经做出选择,将性能置于完全灵 active 之上。任何用作 __dict__dict 子类都将被访问,就好像它是一个普通的 dict (如果子类正在做一些事情,这可能会有点麻烦魔术存储一个值,同时假装它存储不同的值,因为魔术被绕过了),并且所有不是 dict 子类的映射在赋值时被拒绝(你得到一个 TypeError 当您尝试将它们分配给 f.__dict__ 时)。

关于python - Monkeypatching 函数命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50478162/

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