了解Python的内建运算符重载行为

时间:2019-09-22 11:15:48

标签: python python-3.x

++=运算符重载上的列表和元组行为:

这失败了:

>>> [1,2] + (3,4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list

但这可行:

>>> l = [1,2]
>>> l += (3,4)
>>> l
[1, 2, 3, 4]

设置和冻结设置的行为不同:

这有效:

>>> {1,2} | frozenset({3,4})
{1, 2, 3, 4}

这也有效:

>>> s = {1,2}
>>> s |= frozenset({3,4})
>>> s
{1, 2, 3, 4}

为什么[1,2] + (3,4){1,2} | frozenset({3,4})的工作方式不同?

为什么两者不同?是否有一个原因?是向后兼容的东西还是与内部相关的东西?

我对为什么的实现方式更感兴趣,而这种实现方式不是 what 技术上是在后台进行的。我怀疑Python语言是经过精心设计的,我想理解这种差异的原因。

1 个答案:

答案 0 :(得分:0)

主要区别在于实现方式不一致且令人讨厌。

在此示例中:

x

人们会期望y会转换为>>> l = [1,2] >>> l += (3,4) 并失败,但是l += (3, 4) / l = l + (3, 4)的实现是不同的,并且会更改原始对象 。但这实际上可以大致理解为:

list.__iadd__

通过校准set.__iadd__,可以(可能)任何可迭代的方式调用它:

l.extend((3, 4))

这样做可能是出于效率方面的考虑,但是它是隐式的,并且很容易出错。这使它成为惯用的代码模式:

list.extend

更好地扩展 ,而无需用户考虑。

出于性能原因,对本机数据结构的自定义实现(>>> l = [1] >>> l += {11, 31, 21} # <--- this should be a lot more troubling (no order) >>> l [1, 11, 21, 31] # worked, but obviously no order guarantees l = [] for items in items_generator: l += items )是例外。