是否可以在 Python 中的实例级别覆盖 __getitem__?

Is it possible to override __getitem__ at instance level in Python?

使用以下代码:

import types

class Foo():
    def __getitem__(self, x):
        return x

def new_get(self, x):
    return x + 1

x = Foo()
x.__getitem__ = types.MethodType(new_get, x)

x.__getitem__(42) 将 return 43,但 x[42] 将 return 42.

有没有办法在 Python 中的实例级别覆盖 __getitem__

不幸的是,这是不允许的:

For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.

来源:https://docs.python.org/3/reference/datamodel.html#special-lookup

不要这样做...

项目查找协议将始终从 class 中恢复 __getitem__,它甚至不会查看实例 __dict__。一般来说,这实际上是一件好事,因为否则会允许相同 class 的实例在概念上彼此不同,这与 classes.

背后的整个想法背道而驰。

但是...

尽管如此,在某些情况下这可能会有所帮助,例如在出于测试目的进行猴子修补时。

因为直接在 class 级别查找 dunder,所以项目查找逻辑也必须在 class 级别更新。

因此,解决方案是更新 __getitem__,以便它首先在实例 __dict__.

中查找实例级函数

这是一个示例,其中我们正在 classing dict 以允许实例级 __getitem__

class Foo(dict):
    def __getitem__(self, item):
        if "instance_getitem" in self.__dict__:
            return self.instance_getitem(self, item)
        else:
            return super().__getitem__(item)

foo = Foo()
foo.instance_getitem = lambda self, item: item + 1
print(foo[1]) # 2