gpt4 book ai didi

python - 不可变容器内的可变类型

转载 作者:太空狗 更新时间:2023-10-29 18:24:39 24 4
gpt4 key购买 nike

我对修改元组成员有点困惑。以下不起作用:

>>> thing = (['a'],)
>>> thing[0] = ['b']
TypeError: 'tuple' object does not support item assignment
>>> thing
(['a'],)

但这确实有效:

>>> thing[0][0] = 'b'
>>> thing
(['b'],)

也有效:

>>> thing[0].append('c')
>>> thing
(['b', 'c'],)

不起作用,但起作用(哈?!):

>>> thing[0] += 'd'
TypeError: 'tuple' object does not support item assignment
>>> thing
(['b', 'c', 'd'],)

看似等同于以前的,但有效:

>>> e = thing[0]
>>> e += 'e'
>>> thing
(['b', 'c', 'd', 'e'],)

那么游戏规则到底是什么,什么时候可以修改元组中的某些内容?这似乎更像是禁止对元组成员使用赋值运算符,但最后两种情况让我感到困惑。

最佳答案

您可以始终修改元组中的可变值。您看到的令人费解的行为

>>> thing[0] += 'd'

是由+=引起的。 += 运算符执行就地加法,但也是 赋值 — 就地加法只对文件有效,但赋值失败,因为元组是不可变的。想起来像

>>> thing[0] = thing[0] + 'd'

更好地解释了这一点。我们可以使用 dis module从标准库中查看从两个表达式生成的字节码。使用 += 我们得到一个 INPLACE_ADD 字节码:

>>> def f(some_list):
... some_list += ["foo"]
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (some_list)
3 LOAD_CONST 1 ('foo')
6 BUILD_LIST 1
9 INPLACE_ADD
10 STORE_FAST 0 (some_list)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE

使用 + 我们得到一个 BINARY_ADD:

>>> def g(some_list):
... some_list = some_list + ["foo"]
>>> dis.dis(g)
2 0 LOAD_FAST 0 (some_list)
3 LOAD_CONST 1 ('foo')
6 BUILD_LIST 1
9 BINARY_ADD
10 STORE_FAST 0 (some_list)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE

请注意,我们在两个 地方都得到了一个STORE_FAST。这是当您尝试存储回元组时失败的字节码 — 之前出现的 INPLACE_ADD 工作正常。

这解释了为什么“不起作用,但起作用”的情况会留下修改后的列表:元组已经引用了列表:

>>> id(thing[0])
3074072428L

然后 INPLACE_ADD 修改列表,STORE_FAST 失败:

>>> thing[0] += 'd'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

所以元组仍然引用相同列表,但列表已就地修改:

>>> id(thing[0])
3074072428L
>>> thing[0]
['b', 'c', 'd']

关于python - 不可变容器内的可变类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9172263/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com