当我编写一个函数时,当我尝试两种方法时,我发现了一些有趣的东西。一种方法使用索引,另一种使用迭代器:
索引方法:
A = [1,1,1,1]
def flipBits(A):
for i in range(len(A)):
if A[i] == 1:
A[i] = 0
else:
A[i] = 1
return A
>>> flipBits(A)
[0, 0, 0, 0]
迭代器方法:
A = [1,1,1,1]
def flipBits(A):
for bit in A:
if bit == 1:
bit = 0
else:
bit = 1
return A
>>> flipBits(A)
[1, 1, 1, 1]
如果我没有弄错,迭代器只是指向某些数据的指针的副本。因此,当我尝试将位设置为某个位置时,它只设置副本,而不是列表的实际元素。
这是对的吗?还有什么我应该知道的吗?感谢。
答案 0 :(得分:2)
如果我没有弄错,迭代器只是指向某些数据的指针的副本。
这是正确的,但并非完全如此。主要的困惑是您没有直接处理第二个代码块中的任何迭代器。 是正在使用的迭代器(在for
循环内),并且对某些数据有一个引用(换句话说就是指针),但它们并不是同一个东西。 bit
变量仅获取迭代器对产生的值的引用。它不是迭代器本身。
您可以编写自己的for
循环版本,显式处理迭代器。您没有for bit in A:
,而是拥有:
_iterator = iter(A)
while True:
try:
bit = next(_iterator)
except StopIteration:
break
# body of the for loop goes here!
del _iterator
请注意bit
在循环的每个循环中分配其值。如果您稍后重新分配它(在原始循环的主体中),原始值或它来自的列表都不会被修改。
您可以在第一个代码的略微修改版本中看到类似的事情:
def flipBits(A):
for i in range(len(A)):
bit = A[i]
if bit == 1:
bit = 0
else:
bit = 1
return A
此版本不会修改A
,原因与代码的for
循环版本没有相同。重新绑定bit
(这是一个局部变量)与重新绑定A[i]
不同,即使它们都是对相同值的引用。
请注意,如果您不需要来修改A
,那么更多的" Pythonic"解决这个问题的方法是使用列表解析创建一个包含翻转位的新列表:
def flipBits(A):
return [1-bit for bit in A] # you could also use "0 if bit == 1 else 1" instead of 1-bit
答案 1 :(得分:1)
当您使用for
循环时,您将创建一个新的引用变量,该变量依次设置为序列中的每个对象。
当您使用=
时,它会将左侧的引用设置为右侧的对象。
在第一种情况下,A[i]
是对列表元素的直接引用,因此列表会更新。
在第二种情况下,b
是与列表分开的引用;它是由for
循环创建的。更新它不会改变原始列表。