我试图了解使用d[key] += diff
. 我有一些帮助类来跟踪魔术方法调用:
class sdict(dict):
def __setitem__(self, *args, **kargs):
print "sdict.__setitem__"
return super(sdict, self).__setitem__(*args, **kargs)
def __delitem__(self, *args, **kargs):
print "sdict.__delitem__"
return super(sdict, self).__delitem__(*args, **kargs)
def __getitem__(self, *args, **kargs):
print "sdict.__getitem__"
return super(sdict, self).__getitem__(*args, **kargs)
def __iadd__(self, *args, **kargs):
print "sdict.__iadd__"
return super(sdict, self).__iadd__(*args, **kargs)
def __add__(self, *args, **kargs):
print "sdict.__add__"
return super(sdict, self).__add__(*args, **kargs)
class mutable(object):
def __init__(self, val=0):
self.value = val
def __iadd__(self, val):
print "mutable.__iadd__"
self.value = self.value + val
return self
def __add__(self, val):
print "mutable.__add__"
return mutable(self.value + val)
有了这些工具,让我们开始潜水吧:
>>> d = sdict()
>>> d["a"] = 0
sdict.__setitem__
>>> d["a"] += 1
sdict.__getitem__
sdict.__setitem__
>>> d["a"]
sdict.__getitem__
1
我们没有看到__iadd__
这里调用了任何操作,这是有道理的,因为左侧表达式d["a"]
返回一个未实现该__iadd__
方法的整数。我们确实看到 python 神奇地将+=
运算符转换为__getitem__
和__setitem__
调用。
继续:
>>> d["m"] = mutable()
sdict.__setitem__
>>> d["m"] += 1
sdict.__getitem__
mutable.__iadd__
sdict.__setitem__
>>> d["m"]
sdict.__getitem__
<__main__.mutable object at 0x106c4b710>
在这里,+=
操作员成功地调用了一个__iadd__
方法。看起来该+=
运算符实际上被使用了两次:
- 一次用于魔术翻译
__getitem__
并__setitem__
调用 - 第二次
__iadd__
打电话。
我需要帮助的地方如下:
+=
将操作员转换为__getitem__
呼叫__setitem__
的确切技术机制是什么?- 在第二个例子中,为什么
+=
使用了两次操作符?python不会将语句翻译成d["m"] = d["m"] + 1
(在这种情况下我们不会看到__add__
被调用而不是__iadd__
?)