我刚刚在Python 2.6中尝试了以下内容:
>>> foo = (set(),)
>>> foo[0] |= set(range(5))
TypeError: 'tuple' object does not support item assignment
>>> foo
(set([0, 1, 2, 3, 4]),)
>>> foo[0].update(set(range(10)))
>>> foo
(set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),)
Run Code Online (Sandbox Code Playgroud)
我在这里有几个问题:
foo[0] |= set(range(5))更新集合并抛出异常?foo[0].update(set(range(10)))问题?它应该与第一个声明没有相同的结果吗?编辑许多人都指出,元组是不可改变的.我知道这一点.他们还指出,这|=将创建一个新set对象并将其分配给元组.那是错的.看到这个:
>>> foo = set()
>>> bar = foo
>>> foo is bar
True
>>> foo |= set(range(5))
>>> foo
set([0, 1, 2, 3, 4])
>>> bar
set([0, 1, 2, 3, 4])
>>> foo is bar
True
Run Code Online (Sandbox Code Playgroud)
这意味着没有创建新对象,但现有对象已被修改.这应该与元组一起使用.请注意,尽管我的第一个代码抛出了a TypeError,但元组中的集仍然会更新.这就是我感兴趣的效果.为什么TypeError操作显然是成功的?
jch*_*chl 11
>>> def f():
... x = (set(),)
... y = set([0])
... x[0] |= y
... return
...
>>> import dis
>>> dis.dis(f)
2 0 LOAD_GLOBAL 0 (set)
3 CALL_FUNCTION 0
6 BUILD_TUPLE 1
9 STORE_FAST 0 (x)
3 12 LOAD_GLOBAL 0 (set)
15 LOAD_CONST 1 (0)
18 BUILD_LIST 1
21 CALL_FUNCTION 1
24 STORE_FAST 1 (y)
4 27 LOAD_FAST 0 (x)
30 LOAD_CONST 1 (0)
33 DUP_TOPX 2
36 BINARY_SUBSCR
37 LOAD_FAST 1 (y)
40 INPLACE_OR
41 ROT_THREE
42 STORE_SUBSCR
5 43 LOAD_CONST 0 (None)
46 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
这表明该语句x[0] |= y是通过调用x[0].__ior__(y)然后分配返回值来实现的x[0].
set|=通过set.__ior__返回就地实现self.但是,x[0]仍然会进行分配.它分配已经存在的相同值的事实是无关紧要的; 它失败的原因相同:
x = (set(),)
x[0] = x[0]
Run Code Online (Sandbox Code Playgroud)
失败.