wim*_*wim 10 python tuples list mutable immutability
我对修改元组成员有点困惑.以下不起作用:
>>> thing = (['a'],)
>>> thing[0] = ['b']
TypeError: 'tuple' object does not support item assignment
>>> thing
(['a'],)
Run Code Online (Sandbox Code Playgroud)
但这确实有效:
>>> thing[0][0] = 'b'
>>> thing
(['b'],)
Run Code Online (Sandbox Code Playgroud)
还有效:
>>> thing[0].append('c')
>>> thing
(['b', 'c'],)
Run Code Online (Sandbox Code Playgroud)
不起作用,并且有效(嗯?!):
>>> thing[0] += 'd'
TypeError: 'tuple' object does not support item assignment
>>> thing
(['b', 'c', 'd'],)
Run Code Online (Sandbox Code Playgroud)
看似与以前相同,但有效:
>>> e = thing[0]
>>> e += 'e'
>>> thing
(['b', 'c', 'd', 'e'],)
Run Code Online (Sandbox Code Playgroud)
那么,当你能够并且不能修改元组内的某些内容时,游戏的规则到底是什么?它似乎更像禁止使用赋值成员的赋值运算符,但最后两个案例让我感到困惑.
Mar*_*ler 11
您始终可以修改元组内的可变值.你看到的令人费解的行为
>>> thing[0] += 'd'
Run Code Online (Sandbox Code Playgroud)
是由...引起的+=.该+=运营商不就地此外但还一个任务 -就地除了刚工作的文件,但由于元组是不可变的分配失败.想一想就好
>>> thing[0] = thing[0] + 'd'
Run Code Online (Sandbox Code Playgroud)
更好地解释了这个 我们可以使用标准库中的dis模块来查看从两个表达式生成的字节码.随着+=我们得到了一个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
Run Code Online (Sandbox Code Playgroud)
随着+我们得到一个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
Run Code Online (Sandbox Code Playgroud)
请注意,我们STORE_FAST在两个地方都得到了一个.这是当你尝试存储回元组时失败的字节码 - INPLACE_ADD这是在工作正常之前发生的.
这就解释了为什么"不工作,无效"的情况会使修改后的列表落后:元组已经有了对列表的引用:
>>> id(thing[0])
3074072428L
Run Code Online (Sandbox Code Playgroud)
该名单随后被修改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
Run Code Online (Sandbox Code Playgroud)
因此元组仍然具有对同一列表的引用,但列表已就地修改:
>>> id(thing[0])
3074072428L
>>> thing[0]
['b', 'c', 'd']
Run Code Online (Sandbox Code Playgroud)
您不能修改元组,但可以修改元组中包含的事物的内容。列表(与套,http://stardict.sourceforge.net/Dictionaries.php下载,和对象一起)是一个引用类型,因此“东西”在该元组仅仅是一个参考-实际列表是其由参考指向和可在不改变被修改可变对象参考自身。
( + ,) <--- your tuple (this can't be changed)
|
|
v
['a'] <--- the list object your tuple references (this can be changed)
Run Code Online (Sandbox Code Playgroud)
之后thing[0][0] = 'b':
( + ,) <--- notice how the contents of this are still the same
|
|
v
['b'] <--- but the contents of this have changed
Run Code Online (Sandbox Code Playgroud)
之后thing[0].append('c'):
( + ,) <--- notice how this is still the same
|
|
v
['b','c'] <--- but this has changed again
Run Code Online (Sandbox Code Playgroud)
+=错误的原因是它并不完全等同于.append()- 它实际上做了一个添加然后一个赋值(并且赋值失败),而不仅仅是就地附加。