当前位置: 首页 > 面试题库 >

Python-为什么+ =在列表上表现异常?

李明贤
2023-03-14
问题内容

+=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.bar
print g.bar 

f.bar += [3]
print f.bar
print g.bar

f.bar = f.bar + [4]
print f.bar
print 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似乎以我希望事情表现的方式表现。

该+=运算符称为“化合物赋值运算符”。


问题答案:

一般的答案是+=尝试调用__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 += b,a = a + b它们是等效的。这就是让你+=在不可变类型上使用的原因,这似乎是一个奇怪的设计决定,除非你考虑到否则无法+=在数字等不可变类型上使用!



 类似资料:
  • 我现在想要一个数据结构,就像一个有索引的Deque。因此,它应该有O(1)在前面和后面添加和删除元素,以及O(1)基于索引访问元素。这并不难想象一个适合这种情况的设置。 ArrayDeque似乎是一个自然的选择。但是,ArrayDeque不实现List。由于底层数据结构是一个数组,是否有充分的理由不允许索引? 还有,更实用的是,有人知道有哪个图书馆在做我想做的事情吗。据我所知,Apache Com

  • 问题内容: 在中,我们具有接口List和类: 并扩展AbstractList和 我的问题:为什么ArrayList有该implements List条款? 如果,我们不能说吗? 问题答案: 是。可以省略。但是,这是一个立即可见List。否则,将需要额外单击代码/文档。我认为这就是原因-清晰。 并补充的评论-这是为了展示该工具。总体而言,这只是为了方便起见,并减少了List实现之间的代码重复。

  • 问题内容: 所以我有这个临时字符串,基本上是字符串格式的列表。。。我正在尝试将其重新列出,但是我不确定这样做的简单方法。我知道一种方法,但我宁愿不使用正则表达式 如果我使用temp.split()我得到 问题答案: 用途: 安全地评估表达式节点或包含Python表达式的Unicode或Latin-1编码的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串,数字,元组,列表,字典,

  • 问题内容: 如果我有包含10个元素的列表: 为什么l [10]返回IndexError,而l [-1]返回0? 如果列表中没有以前的元素,我想做的就是抛出一个错误。 问题答案: 在Python中,负列表索引表示从列表右边开始计数的项(即的简写形式)。 如果发现需要负索引来指示错误,那么您可以简单地检查这种情况并亲自引发异常(或在那里进行处理):

  • 在一个空列表中,当循环计算到时发生的过程是什么? 例如: 本质上,我想知道

  • 因此,当增加randint()中的界限时,排序列表上的循环会变慢。为什么?