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

a + = b与a = a + b不同

漆雕成弘
2023-03-14
问题内容

今天,我发现了python语言一个有趣的“功能”,这让我感到非常悲伤。

>>> a = [1, 2, 3]
>>> b = "lol"
>>> a = a + b 
TypeError: can only concatenate list (not "str") to list
>>> a += b
>>> a
[1, 2, 3, 'l', 'o', 'l']

那个怎么样?我以为两者是等同的!更糟糕的是,这是我调试时遇到的麻烦的代码

>>> a = [1, 2, 3]
>>> b = {'omg': 'noob', 'wtf' : 'bbq'}
>>> a = a + b
TypeError: can only concatenate list (not "dict") to list
>>> a += b
>>> a
[1, 2, 3, 'omg', 'wtf']

WTF!我的代码中包含列表和字典,并且想知道我到底怎么把dict的键附加到列表上而又没有调用.keys()。事实证明,这就是方法。

我认为这两个陈述是等效的。即使忽略这一点,我也可以理解将字符串追加到列表的方式(因为字符串只是字符数组),但是词典呢?也许如果它附加了(键,值)元组的列表,但是仅获取要添加到列表中的键似乎完全是任意的。

有人知道背后的逻辑吗?


问题答案:

通常,这始终是可变性的问题,尤其是运算符重载。C ++并不更好。

该表达式a + b从绑定到a和的对象(b未修改)计算一个新列表。将其分配回时a,您将更改一个变量的绑定以指向新值。预计这+是对称的,因此您无法添加字典和列表。

该语句a += b修改绑定到的现有列表a。由于它不会更改对象标识,因此更改对表示的对象的所有绑定都是可见的a。运算符+=显然不是对称的,它等效于list.extend,它在第二个操作数上进行迭代。对于字典,这意味着列出密钥。

讨论:

如果对象没有实现+=,则Python将使用+和将其转换为等效语句=。因此 有时是等效的, 具体取决于所涉及对象的类型。

+=更改引用对象(与作为引用的操作数值相反)的a的好处是,在不相应增加实现复杂性的情况下,实现可以更高效。

在其他语言中,您可能会使用更明显的表示法。例如,在没有操作符重载的虚拟版本的Python中,您可能会看到:

a = concat(a, b)

a.extend(a, b)

操作符实际上只是这些的简写。

奖金:

也可以尝试其他可迭代对象。

>>> a = [1,2,3]
>>> b = "abc"
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
>>> a += b
>>> a
[1, 2, 3, 'a', 'b', 'c']

能够执行此操作很有用,因为您可以将生成器附加到带有的列表中+=并获取生成器内容。不幸的是,它破坏了与的兼容性+,但是很好。



 类似资料:
  • 问题内容: 我尝试了一些代码,使用XOR在Java中交换两个整数而不使用第三个变量。 这是我尝试的两个交换函数: 这段代码产生的输出是这样的: 我很好奇,为什么这样说: 与这个不同吗? 问题答案: 问题是评估的顺序: 参见JLS第15.26.2节 首先,对左操作数求值以产生一个变量。 如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,并且不会发生赋值。 否则,将保存

  • 我尝试了一些代码在Java中交换两个整数,而不使用第三个变量,即使用XOR。 以下是我尝试的两个交换函数: 该代码产生的输出如下: 我很想知道,为什么会有这样的说法: 和这个不一样?

  • 问题内容: 这是我的第一个问题,我开始学习Python。之间有什么区别: 和 在下面的示例中编写时,它显示不同的结果。 和 问题答案: 在中,在将右侧的表达式赋给左侧之前对其求值。因此,它等效于: 在第二个示例中,运行时已更改的值。因此,结果是不同的。

  • 问题内容: 这是我必须弄清楚怎么可能的代码。我有一个线索,但我不知道该怎么做。我认为这与负数和正数有关,也可能与变量修饰符有关。我是一个初学者,我到处都看过解决方案,但是找不到可用的东西。 问题是:您需要声明和初始化两个变量。如果条件必须为真。 代码: 感谢您抽出宝贵的时间。 问题答案: 这对于基本类型是不可能的。您可以使用带框的整数来实现: 在和比较将使用未装箱的值1,而将比较引用,并会成功,因

  • 我正在阅读SICP的树递归,其中是通过线性递归计算的。 我们还可以制定一个迭代过程来计算斐波那契数。其思想是使用一对整数a和b,初始化为Fib(1)=1和Fib(0)=0,并重复应用同时变换 不难证明,在应用该变换n次后,a和b将分别等于Fib(n1)和Fib(n)。因此,我们可以使用该过程迭代计算斐波那契数 (由Emacs Lisp重写,代替Scheme) “设置a b=a和b=a,我很难把我的

  • 然而,今天我在处理一些代码时,意外地发现以下两个交换给出了不同的结果: 这让我难以置信。有人能给我解释一下这里发生了什么吗?