使用以下代码:
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)
将返回43,但是x[42]
将返回42。
是否可以在Python实例级别覆盖__getitem__
?
答案 0 :(得分:8)
不幸的是,非常令人惊讶的是,这是不允许的:
对于自定义类,仅对特殊方法进行隐式调用 如果定义在对象的类型上,而不是在 对象的实例字典。
来源:https://docs.python.org/3/reference/datamodel.html#special-lookup
答案 1 :(得分:1)
项目查找协议将始终从类中恢复__getitem__
,甚至不会查看实例__dict__
。通常,这实际上是一件好事,因为否则将允许同一类的实例在概念上彼此不同,这与类背后的整个思想背道而驰。
尽管如此,在某些情况下这可能会有所帮助,例如在为测试目的进行猴子修补时。
由于直接在类级别上搜索dunder,因此项查找逻辑也必须在类级别上更新。
因此,一种解决方案是更新__getitem__
,以便它首先在实例__dict__
中查找实例级功能。
在此示例中,我们将dict
子类化以允许实例级__getitem__
。
class Foo(dict):
def __getitem__(self, item):
if "instance_getitem" in self.__dict__:
return self.instance_getitem(self, item)
else:
super().__getitem__(item)
foo = Foo()
foo.instance_getitem = lambda self, item: item + 1
print(foo[1]) # 2