【问题标题】:How does a Python for loop with iterable work?带有可迭代的 Python for 循环如何工作?
【发布时间】:2010-11-20 12:02:52
【问题描述】:

for party in feed.entry 表示什么以及这个 for 循环实际上是如何工作的?

for party in feed.entry:
    print(party.location.address.text)

(我习惯于 C++ 风格的 for 循环,但 Python 循环让我感到困惑。)

【问题讨论】:

标签: python for-loop iterable


【解决方案1】:

feed.entry 是 feed 的属性,它的值是(如果不是,此代码将失败)实现迭代协议的对象(例如数组)并具有 iter 方法,该方法返回迭代器对象

迭代器有next()方法,返回下一个元素或者抛出异常,所以python的for循环其实是:

iterator = feed.entry.__iter__()
while True:
    try:
        party = iterator.next()
    except StopIteration:
        # StopIteration exception is raised after last element
        break

    # loop code
    print party.location.address.text

【讨论】:

  • +1,因为给出等效的低级代码通常是最好的解释;希望我只能给出+0.9,因为第一行应该是iter(feed.entry)(大多数情况下,当您直接调用特殊方法而不是通过内置方法时,您做错了,尽管有例外;- )。
  • 请注意,在 Python 3 中,神奇的 next 方法现在称为 __next__。您可以使用next 内置函数调用它。
【解决方案2】:

feed.entry 是允许迭代的东西,并且包含某种类型的对象。这与c++大致相似:

for (feed::iterator party = feed.entry.begin(); party != feed.entry.end(); ++party) {
   cout << (*party).location.address.text;
}

【讨论】:

  • 如果我没记错的话,这是python工作的年龄(2.0之前)(使用length()、[]和counter)
【解决方案3】:

要将我的 0.05$ 添加到以前的答案中,您可能还想看看enumerate builtin function

for i, season in enumerate(['Spring', 'Summer', 'Fall', 'Winter']):
    print i, season

0 Spring
1 Summer
2 Fall
3 Winter

【讨论】:

    【解决方案4】:

    party 简单地迭代 iterable feed.entry

    看看Dive into Python的解释。

    【讨论】:

    • 不一定是列表。最好称它为可迭代的。
    • 确实如此。但这似乎是一个初学者的问题。我想让回复保持简单。
    【解决方案5】:

    形式上,Python 中的for statement 总是在iterable 上运行——一个可以在其项目上提供iterator 的对象。 for 语句连续获取 next element from the iterator,将其分配给目标名称并使用它运行套件(“body”)。

    #   |name|   |iterable|
    for party in feed.entry:
        # body...
        print(party.location.address.text)
    

    在示例中,feed.entry 是可迭代对象,party 是目标名称,print ... 是套件。迭代器由for 语句自动请求,并保持迭代状态 - 例如如果可迭代是列表,则为下一个元素的索引。


    如果您来自 C++,经典的 for (int i = 0; i &lt; 10; ++i) loop 代表 external iteration:迭代状态 i 保留在可迭代对象之外。这对应于 Python 的 while 循环:

    # for (int i = 0; i < 10; ++i)
    i = 0
    while i < 10:
        i += 1
        # access the state of an iterable here
    

    较新的for (auto party : entry) range loop 表示内部迭代:迭代状态由单独的迭代器保存。这对应于 Python 的 for 循环。然而,iterable/iterator 协议明显不同:Python 的 for 使用 iter(iterable) 获取迭代器,它应该支持 next(iterator) - 返回一个元素或引发 StopIteration

    用 Python 编写,definition of the for statement 对应如下:

    # for party in feed.entry:
    __iterator = iter(feed.entry)  # iterator -- not visible in containing scope
    __iterating = True             # graceful exit to enter `else` clause
    while __iterating:
        try:                          # attempt to...
            item = next(__iterator)   # ... get the next item
        except StopIteration:         # ... or stop
            __iterating = False       #     with a graceful exit
        else:
            party = item
            <suite>                # run the body with names bound
    else:                          # entered in a graceful exit only
        <else suite>
    

    (请注意,从__iterating = True__iterating = False 的整个块对包含范围来说是不“可见的”。实现使用各种优化,例如CPython 允许builtin iterators to return a C NULL instead of raising a Python StopIteration。)

    for 语句只是定义了 如何 使用迭代器和迭代器。如果您最熟悉外部迭代,那么查看可迭代和迭代器也会有所帮助。


    iter(iterable) 调用具有 multiple ways to derive an iterator - 这就像 iter 为各种结构类型重载。

    • 如果定义了type(iterable).__iter__,则作为方法调用,结果作为迭代器。

    • 如果定义了type(iterable).__getitem__,它会被一个泛型迭代器类型包装,该迭代器类型返回iterable[0]iterable[1],...如果在索引时引发IndexError,则引发StopIteration

    无论哪种方式,iter 都会返回 iterator 或引发 TypeError。迭代器是 any 类型,它定义了__iter__(用于可重用性)和__next__(用于实际迭代)。通常,迭代器是可以保存状态以计算__next__ 项的对象。例如,一个列表迭代器对应这个对象:

    class ListIterator:
        """Python equivalent of ``iter(:list)``"""
        # iterator holds iteration state - e.g. iterable and current index
        def __init__(self, iterable: list):
            self.iterable = iterable
            self.index = 0
    
        # __next__ fetches item and advances iteration state - e.g. index += 1
        def __next__(self):
            # attempt to produce an item
            try:
                item = self.iterable[self.index]
            except IndexError:  # translate indexing protocol to iteration protocol
                raise StopIteration
            # update iteration state
            self.index += 1
            return item
    
        # iterators can be iterated on in ``for`` statements etc.
        def __iter__(self):
            return self
    

    (请注意,人们习惯性地将这样的对象写成generator function。)

    索引列表或增加一些指针只是可迭代/迭代器协议的一个非常基本的例子。例如,迭代器可以是无状态的,并在__next__ 中使用random.random() 来产生无限的随机数流。例如,迭代器还可以保存外部信息的状态,并迭代地遍历文件系统。

    【讨论】:

      【解决方案6】:

      在 Python 中,for bucle 不像 C/C++ 的那样,它们最像 PHP 的 foreach。您所做的不是像在 while 中那样使用“(初始化;条件;增量)”进行迭代,它只是迭代列表中的每个元素(字符串像列表一样可迭代)。

      例如:

      for number in range(5):
          print number
      

      会输出

      0
      1
      2
      3
      4
      

      【讨论】:

      • 字符串不是列表。字符串是可迭代的,列表也是,但字符串和列表在 Python 中肯定是两种不同的类型。
      • 嗯,在许多语言中,字符串是字符数组,而在 Python 中,它的行为在迭代时非常相似...编辑...
      • 是的,字符串和列表在迭代时非常相似,但在许多其他情况下却很重要。例如,您不能修改字符串。
      【解决方案7】:

      我只是想为刚接触这个的人提供一个更通用的解释。

      在语法上,for 循环看起来像...

      for <name to be assigned to> in <some sequence>:
      
          <block of code, optionally referencing the name>
      

      解释器为序列中的每个项目(任何可以迭代的项目)运行一次块。每次运行该块时,它首先将序列中的下一个对象分配给该名称,该名称可以是任何有效的变量名称。

      执行for each in (1, 2, 3): print(each) [或多或少] 与执行...

      i = 0
      sequence = (1, 2, 3)
      while True:
          try:
              each = sequence[i]
              print(each)
              i += 1
          except IndexError: pass
      

      你也可以在赋值部分解压参数。就像你可以做类似的事情一样......

      a, b = 1, 2
      

      ...你也可以做...

      for a, b in [(1, 2), (3, 4), (5, 6)]: print(a + b)
      

      ...打印...

      3
      7
      11
      

      【讨论】:

        【解决方案8】:

        Python 的for 循环与iterators 一起使用,它必须实现iterator 协议。更多详情见:

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-17
          • 2015-02-03
          • 2012-06-27
          • 2023-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-18
          相关资源
          最近更新 更多