使用以下代码:
class X( object ):
def __init__( self ):
self.value = 0
def __iadd__( self, value ):
self.value += value
return self
class Y( object ):
def __init__( self ):
self.fields = { 'test': X() }
def __getitem__( self, key ):
return( self.fields[ key ] )
def __getattr__( self, key ):
return self.fields[ key ]
obj = Y()
obj.test += 1
print( obj.test.value )
obj['test'] += 1
print( obj.test.value )
将 __iadd__
与 __getattr__
一起使用会起作用,但是在使用 __getitem__
时会出现错误:
TypeError: 'Y' object does not support item assignment
发生。
我知道 __iadd__
实际上是 x = x.__iadd__(y)
,但是我不知道为什么它不能与 __getitem__ 一起使用
。
谢谢。
最佳答案
obj.test += 1
工作的原因是 obj.__setattr__
有一个允许它工作的默认实现(虽然可能不是你想要的方式工作)——即,它在实例字典中存储对返回的 X
对象的引用。您可以通过以下方式观看它的发生:
>>> obj = Y()
>>> obj.test
<__main__.X object at 0x0000024BF247B220>
>>> obj.__dict__
{'fields': {'test': <__main__.X object at 0x0000024BF247B220>}}
>>> obj.test += 1
>>> obj.__dict__
{'fields': {'test': <__main__.X object at 0x0000024BF247B220>}, 'test': <__main__.X object at 0x0000024BF247B220>}
请注意,现在有一个 test
属性 在您的 fields
字典之外!两个字典都指向的仍然只有一个 X
对象(因为你的 __iadd__
返回了 self
,没有新的 X
曾经被创造过)。
当你执行 obj.test += 1
时,发生的事情是:
obj.__setattr__("test", obj.__getattr__("test").__iadd__(1))
__setattr__
调用在 obj.__dict__
中创建新的“测试”条目。
相反,当您执行 obj["test"] += 1
时,这将转化为:
obj.__setitem__("test", obj.__getitem__("test").__iadd__(1))
__setitem__
引发了异常——与 __setattr__
不同,没有默认的 object.__setitem__
允许 obj[ "test"] = obj["test"] + 1
开始工作。
关于python - 为什么 "__iadd__"在与 "__getitem__"和 "__getattr__"一起使用时表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71858949/