Python bitarray列表与原地异或操作^=的异常行为探究
Python中bitarray列表与异或操作的行为差异解析
复现代码
ls = [bitarray('0'), bitarray('0')] ls[0] ^= bitarray('1') print(ls) # 输出: [bitarray('1'), bitarray('0')] ls = [bitarray('0')]*2 ls[0] ^= bitarray('1') print(ls) # 输出: [bitarray('1'), bitarray('1')] ls = [bitarray('0'), bitarray('0')] ls[0] = ls[0] ^ bitarray('1') print(ls) # 输出: [bitarray('1'), bitarray('0')]
疑问解答
- 疑问1:为什么第二个代码块和第一个结果不同?
你猜的没错,[bitarray('0')]*2确实是复制引用,而非创建两个独立的bitarray对象。整数无法复现该行为的原因是:整数属于Python的不可变类型,对不可变类型执行操作时,会生成新对象而不修改原对象;但bitarray是可变类型,^=是原地修改操作,会直接改变原对象的内容。
用*2创建列表时,两个元素指向同一个bitarray实例,修改其中一个就会同步影响另一个;而第一个代码块里的[bitarray('0'), bitarray('0')]是生成两个独立的bitarray对象,修改其中一个自然不会波及另一个。
- 疑问2:为什么
ls[0] ^= bitarray('1')和ls[0] = ls[0] ^ bitarray('1')结果不同?
这两个操作并非等价简写,核心差异在于是否原地修改对象:^=调用的是bitarray的__ixor__方法,属于原地操作,它直接修改当前列表元素指向的bitarray对象本身,不会改变列表元素的引用关系。ls[0] = ls[0] ^ bitarray('1')中,^调用的是__xor__方法,会生成一个新的bitarray对象,随后将列表第一个元素的引用替换为这个新对象,原对象并未被修改。
所以在第二个代码块的共享引用场景下,^=会修改共享的那个bitarray实例,导致两个列表元素都显示修改后的值;而赋值方式是替换引用,原共享对象保持不变,另一个列表元素仍指向原对象,因此结果和第一个代码块一致。
内容的提问来源于stack exchange,提问作者Nathan Lowry
相关产品推荐
相关产品推荐

