【问题标题】:Adding `__getattr__` method to an existing object instance [duplicate]将`__getattr__`方法添加到现有对象实例[重复]
【发布时间】:2019-05-31 20:55:02
【问题描述】:

我希望这个工作:

import types

def new_getattr(self, *args, **kwargs):
    return 2

class A:
    def __init__(self):
        pass

a = A()
a.__getattr__ = types.MethodType(new_getattr, a)
print(a.anything)

现在,它会抛出 AttributeError: A instance has no attribute 'anything'

我尝试了here 提出的不同解决方案,它们都有效,但不适用于__getattr__

如果我执行print(a.__getattr__('anything')),它实际上会打印2;问题是当我执行a.anything 时不会自动调用我的__getattr__ 方法。


附带说明一下,在我的实际实现中,我不能修改类A 的定义,也不能输入它的名称并执行类似A.__getattr__ = ... 的操作(这可行),因为我需要它是通用的并且独立于类名。

编辑:我最终这样做了:

a.__class__.__getattr__ = new_getattr.

【问题讨论】:

  • 你不能a.__getattr__ = types.MethodType(new_getattr, a.__class__)吗?
  • @grooveplex 我刚刚想到了!甚至像 a.__class__.__getattr__ = types.MethodType(new_getattr, a) 这样的东西也可以工作。
  • 太棒了!介意我将其发布为答案吗? :)
  • @grooveplex 继续!

标签: python


【解决方案1】:

您不能 - __dunder__ 名称在类型上解析,而不是每个实例。自定义__getattr__ 需要直接在A 上定义。

请参阅数据模型文档的Special method lookup 部分,具体而言:

对于自定义类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。

注意:如果你只有一个实例的引用,而不是类,仍然可以通过为type(a) 返回的对象分配一个方法来修改类型。请注意,这将影响所有现有实例,而不仅仅是 a 实例。

【讨论】:

    猜你喜欢
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多