是否可以在 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
使用以下代码:
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