Python字典“;加上“相等”;行为
我试图理解使用Python字典“;加上“相等”;行为,python,dictionary,operators,magic-methods,mutators,Python,Dictionary,Operators,Magic Methods,Mutators,我试图理解使用d[key]+=diff更新python字典背后的确切机制。我有一些助手类来跟踪魔术方法调用: class sdict(dict): def __setitem__(self, *args, **kargs): print "sdict.__setitem__" return super(sdict, self).__setitem__(*args, **kargs) def __delitem__(self, *args, **ka
d[key]+=diff
更新python字典背后的确切机制。我有一些助手类来跟踪魔术方法调用:
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
我们看不到这里调用的任何\uuuu iadd\uuuu
操作,这是有意义的,因为左侧表达式d[“a”]
返回一个不实现\uu iadd\uu
方法的整数。我们确实看到python神奇地将+=
操作符转换为\uuu getitem\uuuuu
和\uuuu setitem\uuuu
调用
继续:
>>> d["m"] = mutable()
sdict.__setitem__
>>> d["m"] += 1
sdict.__getitem__
mutable.__iadd__
sdict.__setitem__
>>> d["m"]
sdict.__getitem__
<__main__.mutable object at 0x106c4b710>
>d[“m”]=mutable()
sdict.\uuuu设置项__
>>>d[“m”]+=1
sdict.\uu获取项目__
可变的__
sdict.\uuuu设置项__
>>>d[“m”]
sdict.\uu获取项目__
这里,+=
操作符成功地调用了一个\uuIdd\uIdd
方法。看起来+=
运算符实际使用了两次:
- 对于
和\uuuu getitem\uuuuuuu
调用的神奇转换\uuuuuuuu setitem\uuuuuuuuuu
- 第二次用于
调用\uuuu iadd\uuu
- 将
运算符转换为+=
和\uuu getitem\uuuuuuu
调用的确切技术机制是什么\uuuu setitem\uuuuu
- 在第二个示例中,为什么要使用
运算符两次?python是否将语句转换为+=
(在这种情况下,我们不会看到调用d[“m”]=d[“m”]+1
)\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+=
运算符应用于字典。您将其应用于存储在d['a']
键中的值,这是一个完全不同的对象
换句话说,Python将检索d['m']
(a\uuuu getitem\uuuu
调用),对其应用+=
操作符,然后将该表达式的结果设置回d['m']
(\uu setitem\uu
调用)
\uuuu iadd\uuu
方法要么返回原地变异的self
,要么返回一个新对象,但Python无法确定该方法返回了什么。因此它必须始终调用d.\uuu setitem('m')
如果你这样做了,同样的事情也会发生:
m = d['m']
m += 1
d['m'] = m
但是在全局命名空间中没有额外的名称m
如果mutable()
这记录在以下文件中:
扩充赋值计算目标(与普通赋值语句不同,目标不能是解包)和表达式列表,对两个操作数执行特定于赋值类型的二进制运算,并将结果赋值给原始目标
其中d['m']
是目标;在这里评估目标涉及到\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,因为,如中所述,\uuuuuuuuuuuuuuuuuuuuuuuuuu,因此,调用了\uuuu setitem\uuuuuu
。我猜,由于“get the value of”操作符已经实现,因此该语句被认为等价于这样的语句:“X=get;X+=1;set(X);”这一切在我看来都非常简单<代码>sdict.\uuuu iadd\uuuu
从未被调用,因为您没有任何代码在sdict
对象上执行+=
。您只对sdict
中的元素执行+=
——在第一种情况下是整数,在第二种情况下是可变的
。但是您已经证明您理解这一点,所以我不确定问题是什么。我想我的困惑在于python将+=
转换为\uuu getitem\uuuuuuuuuu
和\uuuuu setitem\uuuuuuu
调用字典的实际机制。在第二个示例中,它似乎使用了一个+=
操作符两次:一次调用\uuu getitem\uuuuuu
和\uuuu setitem\uuuuu
,第二次调用可变
上的\uuu iadd\uuuu
。这是怎么回事?@moatra:你听了我回答的最后一部分了吗?为了使+=
工作,Python需要首先检索等式左侧的一个对象(\uuu getitem\uuu
),然后应用+=
,然后在完成后,将对象放回它的来源(\uu setitem\uuu
)。我目前的理解是Python将d[“m”+=1
转换为d[“m”=d[“m”]+1
。它是否将其转换为d[“m”]=d[“m”]+=1
?不管在何处指定了此行为?您的理解是错误的。请参阅。如果d['m']
上没有定义\u iadd\ucode>方法,则将应用d['m']=d['m']+1
,但这里的情况并非如此。