python中两个赋值运算符有什么区别?

时间:2013-11-13 18:27:27

标签: python

In [38]: d = set(range(3))

In [39]: d
Out[39]: set([0, 1, 2])

In [40]: for i in d:
    d  -= set([2])
   ....:     
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/home/gridlex/workspace/HomeBackSites/nava_scripts/<ipython-input-40-b79926ab34ec> in <module>()
----> 1 for i in d:
      2     d  -= set([2])
      3 

RuntimeError: Set changed size during iteration

python中这两个赋值有什么区别?

1. d - = set([2])

2 d = d - 设置([2])

In [41]: d = set(range(3))

In [42]: for i in d:
    d = d - set([2])
   ....:     

In [43]: d
Out[43]: set([0, 1])

1 个答案:

答案 0 :(得分:3)

对于像整数这样的不可变类型,a -= ba = a - b是同一个:它创建一个新值a - b,并重新绑定名称a以引用这个新价值而不是旧价值。

但是对于像集一样的可变类型,a -= b会更改a指向就地的值。 (它还会将a重新绑定到它已经引用的相同值,但这并不重要。)

查看此对象的最佳方法是查看对象的标识:

>>> s1 = set(range(3))
>>> s2 = s1
>>> s1, id(s1), s2, id(s2)
({0, 1, 2}, 4303749432, {0, 1, 2}, 4303749432)
>>> s1 -= {1}
>>> s1, id(s1), s2, id(s2)
({0, 2}, 4303749432, {0, 2}, 4303749432)
>>> s1 = s1 - {2}
>>> s1, id(s1), s2, id(s2)
({0}, 4303749664, {0, 2}, 4303749432)

请注意-=离开s1仍然引用与s2相同的集合,并更改该集合; -离开s1引用了一个具有不同id的全新集合,但不影响s2


在幕后,a = a - b大致相当于a = a.__sub__(b),而a -= b相当于a = a.__isub__(b)。除非没有__isub__方法,a -= b只会使用__sub__

__isub__更改值的事实虽然__sub__返回一个新值,但该语言并未真正强制执行,但它对所有内置和stdlib类型都是正确的,并且预计适用于任何自定义类型。它在文档中的Emulating numeric types中描述:

  

这些[__ifoo__]方法应该尝试就地执行操作(修改 self )并返回结果(可能是,但不一定是)。如果未定义特定方法,则扩充分配将回退到常规方法。例如,要执行语句x += y,其中 x 是具有__iadd__()方法的类的实例,则调用x.__iadd__(y)。如果 x 是未定义__iadd__()方法的类的实例,则会考虑x.__add__(y)y.__radd__(x),与{{1}的评估一样}。


*由于(a)x + y,(b)用C实现的类型(如__rsub__)和(c)查找规则,因此 某些特殊方法与普通方法不同。