Sta*_*ean 11 python monkeypatching
使用以下代码:
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)
Run Code Online (Sandbox Code Playgroud)
x.__getitem__(42)将返回43,但x[42]将返回42。
有没有一种方法可以__getitem__在Python实例级别进行覆盖?
不幸的是,非常令人惊讶的是,这是不允许的:
对于自定义类,只有在对对象的类型(而不是在对象的实例字典中)定义的情况下,才能保证对特殊方法的隐式调用可以正常工作。
Source: https://docs.python.org/3/reference/datamodel.html#special-lookup
项目查找协议将始终__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:
return super().__getitem__(item)
foo = Foo()
foo.instance_getitem = lambda self, item: item + 1
print(foo[1]) # 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
222 次 |
| 最近记录: |