python - 如果元组不包含 __iadd__ 但仍使用 INPLACE_ADD 指令,则就地添加如何在元组中工作?

标签 python list tuples in-place

我们知道tuple不支持项目分配,但我们可以执行inplace add然而,对于元组,这创建一个新对象,因为元组是不可变的。例如:

>>> t1 = (1, 2)
>>> id(t1)
154311048
>>> t1 += (3, 4)
>>> t1
(1, 2, 3, 4)
>>> id(t1)
157955320

这一切都很好。另一方面,list s 是可变的,并且在执行就地添加时不会创建新对象。

现在我的印象是 python 中的就地添加是用 __iadd__ 实现的魔法,所以:

>>> l1 = [1,2,3]
>>> l1 += [4, 5]
# is same as
>>> l1 = l1.__iadd__([4,5])   # 1
# but, again for lists, this is also same as, simply
>>> l1.__iadd__([4,5])        # 2

我推测,由于不可变对象(immutable对象)不能保证就地操作,因此 python 分配 l1.__iadd__([4,5])l1 ,否则,对于列表,只需调用 l1.__iadd__([4,5])而不将其分配回 l1将修改 l1到位。

因此,考虑到这一点,我猜元组可能会像这样工作,即,

>>> t1 = t1.__iadd__((3,4))

但是,

Traceback (most recent call last):

File "<ipython-input-12-e8ed2ace9f7f>", line 1, in <module> t1.__iadd__((1,2))

AttributeError: 'tuple' object has no attribute '__iadd__'

确实,'__iadd__' in dir(tuple)计算结果为 False 。然后我想,可能是在内部,Python 用元组创建了一个列表,执行 __iadd__并将结果转换回tuple (我不知道为什么有人会这样做!此外,这并不能解释元组相对于列表的性能优势)或对于不可变对象(immutable对象),__iadd__可能只是回退到 __add__并返回值,但在执行 dis 之后:

>>> from dis import dis
>>> dis('t1 += (3, 4)')
  1           0 LOAD_NAME                0 (t1)
              2 LOAD_CONST               0 ((3, 4))
              4 INPLACE_ADD
              6 STORE_NAME               0 (t1)
              8 LOAD_CONST               1 (None)
             10 RETURN_VALUE

但是字节码有指令INPLACE_ADD ! 对于列表,它是这样的:

>>> dis('l1 += [1,2]')
  1           0 LOAD_NAME                0 (l1)
              2 LOAD_CONST               0 (1)
              4 LOAD_CONST               1 (2)
              6 BUILD_LIST               2
              8 INPLACE_ADD
             10 STORE_NAME               0 (l1)
             12 LOAD_CONST               2 (None)
             14 RETURN_VALUE

此外,如果是 list有一个额外的指令BUILD_LIST ,所以tuples也不要建立 list !

正如你所看到的,这对我来说非常令人困惑。有人可以解释一下发生了什么事吗?这是如何工作的?

最佳答案

如果__iadd__不存在或返回

INPLACE_ADD,则使用__add____radd__回退到常规加法未实现

关于python - 如果元组不包含 __iadd__ 但仍使用 INPLACE_ADD 指令,则就地添加如何在元组中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60407384/

相关文章:

python - 在 setup.py 中包含 CefPython 库

python - 列表中 list() 的开销

Python 以列表中给定元素之前的元素为目标

Haskell:代数数据与元组

Python - 使用元组作为列表索引

python - 使用 VLC 的 Python 绑定(bind)时,选项 --plugin-path 不再存在错误

python - 在行(字符串)中找到子字符串后打印下一行,直到满足条件

python - 在 2D 图上绘制具有 3 个特征的分类决策树的决策面

java - 如何将 HashMap 值传递给列表

list - Haskell 递增元组的最后一个元素