在Python中是否可以在实例级别重写_getitem __?
使用以下代码:在Python中是否可以在实例级别重写_getitem __?,python,monkeypatching,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) x.\uu getitem\uu42将返回43,但x[42]将返回42 在Python中,有没有一种方法可以在实例级别重写\uuu getit
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.\uu getitem\uu42
将返回43,但x[42]
将返回42
在Python中,有没有一种方法可以在实例级别重写
\uuu getitem\uuu
对于自定义类,特殊方法的隐式调用仅限于
如果在对象的类型上定义,而不是在
对象的实例字典
来源:不要这样做。。。
项查找协议将始终从类中恢复\uuuuu getitem\uuuuuuuuuu
,它甚至不会查看实例\uuuuuuuu dict\uuuuuuuu
。这实际上是一件好事,因为如果不这样做,将允许同一类的实例在概念上彼此不同,这与类背后的整个思想背道而驰
但是
尽管如此,在某些情况下,这可能是有帮助的,例如,当为测试目的进行猴子补丁时
因为dunder是在类级别直接查找的,所以项查找逻辑也必须在类级别更新
因此,一种解决方案是更新\uuuu getitem\uuuuuuu
,以便它首先在实例\uuuu dict\uuuuu
中查找实例级函数
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
下面是一个示例,其中我们正在子类化dict
,以允许实例级别\uu getitem\uu
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
我肯定你无论如何都不想这么做。从概念上讲,具有不同方法定义的对象不再是类的一部分。如果您想了解全部情况:我想对某个进程计时,因此基本上,我通过添加代码来计时对这些方法的调用,从而覆盖我想计时的实例的方法,特别是,我想对
\uu getitem\uuuuu
的调用执行此操作。(其思想是修改对象,将其传递给一些现有代码,并记录每次调用方法所花费的时间)。相关:(文本实际上是错误的;并不是所有的特殊方法都依赖于类级绑定,但您不能指望它们中的任何一个不依赖于类级绑定,并且它可能会随着版本的变化而变化,因为它们中的任何一个都不正式支持实例级重新绑定)。在文档上搜索了一点,但找不到此信息。非常感谢!我想我必须找到另一个解决方案来实现我想要的解决方案。尝试一下:x.\uuuuuuu class.\uuuuuuu base.\uuuuuuu getitem\uuuuuuuu=new\uu get
给出了属性错误:'tuple'object attributer'\uuuuuuu getitem\uuuuuuu'是只读的
,所以你是对的。这并不完全是不正确的幸运的是,如果他们允许的话,您可以自己为序列类下标,例如list[2]
,而不是立即将其视为无意义的拒绝,它必须签入列表。\uuu getitem\uuuu
以确保每次都传递一个列表
实例,而不是类本身。在类上查找它还可以以其他方式加快速度(99.9%的时间来自类上的C级插槽,但每次都必须检查实例字典,以确保它不是被覆盖的<0.1%情况)@ShadowRanger是的,很不幸,这是OP的问题。这是一个很好的建议,但我认为它对我的情况没有帮助。我的想法是,我想在一些不是我写的代码中计时\uuuuuGetItem\uuuuuuuuu
的一些调用。所以我取一个对象,修改它的\uuuGetItem\uuuuuuuu
方法来记录每次调用的时间,然后st将其传递给非我编写的代码。我只需在类级别而不是实例级别执行该操作。@StatisticDean上面的代码片段向您展示了如何使用继承来执行您想要的操作