为了账号安全,请及时绑定邮箱和手机立即绑定

为什么+=在列表上表现得出乎意料?

为什么+=在列表上表现得出乎意料?

BIG阳 2019-06-12 15:15:39
为什么+=在列表上表现得出乎意料?这个+=python中的运算符似乎意外地在列表上操作。有人能告诉我这是怎么回事吗?class foo:        bar = []      def __init__(self,x):          self.bar += [x]class foo2:      bar = []      def __init__(self,x):           self.bar = self.bar + [x]f = foo(1)g = foo(2)print f.barprint g.bar  f.bar += [3]print f.barprint g.bar f.bar = f.bar + [4]print f.barprint g.bar f = foo2(1)g = foo2(2)print f.bar  print g.bar输出量[1, 2][1, 2][1, 2, 3][1, 2, 3][1, 2, 3, 4][1, 2, 3][1][2]foo += bar似乎影响到类的每个实例,而foo = foo + bar看上去就像我所期望的那样。这个+=运算符被称为“复合赋值运算符”。
查看完整描述

3 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

一般的答案是+=试图调用__iadd__方法,如果无法使用该方法,则尝试使用__add__相反。所以问题在于这些特殊方法之间的区别。

这个__iadd__特殊方法是用于就地添加的,即它对其作用的对象进行变异。这个__add__特殊方法返回一个新对象,并用于标准+接线员。

所以当+=运算符用于具有__iadd__定义的对象被修改到位。否则,它将尝试使用普通的__add__并返回一个新对象。

这就是为什么对于列表这样的可变类型+=更改对象的值,而对于元组、字符串和整数等不可变类型,则返回一个新对象(a += b变得等价于a = a + b).

对于支持这两种类型的类型__iadd____add__因此,你必须小心使用哪一个。a += b会打电话__iadd__突变a,鉴于a = a + b将创建一个新对象并将其分配给a..他们不是同一个行动!

>>> a1 = a2 = [1, 2]>>> b1 = b2 = [1, 2]>>> a1 += [3]          # Uses __iadd__, modifies a1 in-place>>> b1 = b1 + [3]      
# Uses __add__, creates new list, assigns it to b1>>> a2[1, 2, 3]              
# a1 and a2 are still the same list>>> b2[1, 2]                 # whereas only b1 was changed

对于不可变类型(在该类型中,您没有__iadd__a += ba = a + b都是等价物。这就是让你使用的东西+=对于不可变的类型,这似乎是一个奇怪的设计决策,直到您考虑到否则您无法使用+=像数字这样的不可变的类型!


查看完整回答
反对 回复 2019-06-12
  • 3 回答
  • 0 关注
  • 322 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信