简体   繁体   English

Python迭代器与索引

[英]Python Iterators vs Indexing

As I was writing a function I came upon something interesting when I tried two methods. 在编写函数时,尝试两种方法时遇到了一些有趣的事情。 One method used indexing, and the other used iterators: 一种方法使用索引,另一种方法使用迭代器:

Indexing Method: 索引方法:

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]

Iterator Method: 迭代器方法:

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]

If I'm not mistaken, an iterator is just a copy of a pointer to some data. 如果我没记错的话,迭代器只是指向某些数据的指针的副本。 So when I try to set the bit to something, it's only setting the copy, not the actual element of the list. 因此,当我尝试将位设置为某项内容时,它仅设置副本,而不是列表的实际元素。

Is this correct? 这个对吗? Anything else I should know? 还有什么我应该知道的吗? Thanks. 谢谢。

If I'm not mistaken, an iterator is just a copy of a pointer to some data. 如果我没记错的话,迭代器只是指向某些数据的指针的副本。

This is sort of correct, but not entirely. 这是正确的,但并非完全正确。 The main confusion is that you're not directly handling any iterators in your second code block. 主要的困惑是您没有直接在第二个代码块中处理任何迭代器。 There is an iterator being used (inside the for loop), and there is a reference (a pointer in other words) to some data, but they're not the same thing. 目前正在使用一个迭代器(里面for循环),并有一个参考(即指针)的一些数据,但它们不是一回事。 The bit variable is only getting a reference to the value yielded by the iterator. bit变量仅获得对迭代器产生的值的引用。 It's not the iterator itself. 不是迭代器本身。

You can write your own version of a for loop, explicitly handling the iterator. 您可以编写自己的for循环版本,显式处理迭代器。 Instead of for bit in A: , you'd have: 不用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

Notice that bit gets its value assigned on each cycle of the loop. 注意,该bit在循环的每个周期都得到分配的值。 If you reassign it later (in the body of the original loop), neither the original value or the list it came from gets modified. 如果稍后再分配它(在原始循环的主体中),则原始值或它来自的列表都不会被修改。

You could see a similar thing happen in a slightly modified version of your first code: 您可能会在第一个代码的稍微修改后的版本中看到类似的情况:

def flipBits(A):
  for i in range(len(A)):
      bit = A[i]
      if bit == 1: 
          bit = 0
      else: 
          bit = 1
  return A

This version will not modify A for the same reason the for loop version of your code did not. 出于与您的代码的for循环版本相同的原因,该版本不会修改A Rebinding bit (which is a local variable) is not the same thing as rebinding A[i] , even though they are both references to the same value. 重新绑定bit (这是一个局部变量)与重新绑定A[i]并不相同,即使它们都引用了相同的值。

Note that if you don't need to modify A in place, a more "Pythonic" way to solve this problem is to create a new list with the flipped bits in it, using a list comprehension: 请注意,如果你没有需要修改A到位,更“Python化”的方式来解决这个问题是建立在它的翻转位一个新的列表,使用列表理解:

def flipBits(A):
    return [1-bit for bit in A] # you could also use "0 if bit == 1 else 1" instead of 1-bit

When you use a for loop, you create a new reference variable that is set to each of the objects in the sequence in turn. 使用for循环时,将创建一个新的引用变量,该变量依次设置为序列中的每个对象。

When you use = , it sets the reference on the left to the object on the right. 使用= ,它将左侧的引用设置为右侧的对象。

In the first case, A[i] is a direct reference to an element of your list so the list gets updated. 在第一种情况下, A[i]是对列表元素的直接引用,因此列表将得到更新。

In the second case, b is a reference that is separate from the list; 在第二种情况下, b是与列表分开的引用; it was created by the for loop. 它是由for循环创建的。 Updating it does not change the original list. 更新它不会更改原始列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM