5

我非常困惑。我有一块 HTML 是我从一个更大的表格中刮下来的。它看起来像这样:

<td align="left" class="page">Number:\xc2\xa0<a class="topmenu" href="http://www.example.com/whatever.asp?search=724461">724461</a> Date:\xc2\xa01/1/1999 Amount:\xc2\xa0$2.50 <br/>Person:<br/><a class="topmenu" href="http://www.example.com/whatever.asp?search=LAST&amp;searchfn=FIRST">LAST,\xc2\xa0FIRST </a> </td>

(实际上,它看起来更糟,但我正则表达式掉了很多换行符)

我需要把这些线弄出来,把日期/金额线分开。开始的地方似乎是找到那个 HTML 块的孩子。该块是一个字符串,因为这就是正则表达式将它还给我的方式。所以我做了:

text_soup = BeautifulSoup(text)
text_children = text_soup.find('td').childGenerator()

我发现我只能迭代text_children一次,但我不明白为什么会这样。这是一种listiterator类型,我很难理解。

我习惯于假设如果我可以使用 for 循环遍历某些内容,我可以使用诸如 text_children[0] 之类的内容调用任何一个元素。迭代器似乎并非如此。如果我创建一个列表:

my_array = ["one","two","three"] 

我可以my_array[1]用来查看数组中的第二项。如果我尝试这样做,text_children[1]我会收到一个错误:

TypeError: 'listiterator' object is not subscriptable

如何获取迭代器的内容?

4

3 回答 3

12

您可以通过以下方式轻松地从迭代器构造一个列表:

my_list = list(your_generator)

现在您可以为元素下标:

print(my_list[1])

另一种获取价值的方法是使用next. 这将从迭代器中拉出下一个值,但是正如您已经发现的那样,一旦您从迭代器中拉出一个值,您就不能总是将其放回(是否可以放回完全取决于正在迭代的对象及其next方法的实际外观)。

这样做的原因是您通常只想要一个可以迭代的对象。迭代器对此非常有用,因为它们一次计算元素 1 而不需要存储所有值。换句话说,您一次只有一个来自迭代器的元素消耗系统的内存——与列表或元组相比,所有元素通常在开始迭代之前都存储在内存中。

于 2012-11-21T14:39:54.487 回答
2

正如我之前所说,简短的回答是从您的生成器创建一个列表。

像这样:list(generator)

长答案,以及原因的解释:

当你创建一个生成器,或者在你的情况下是一个“listiterator”,它是一个漂亮的汤使用的生成器,你并没有真正创建一个项目列表。您正在创建一个对象(生成器),它知道如何遍历一定数量的项目,一次一个,(next()

那是什么意思。

而不是你想要的,可以说是一本带页面的书。

你得到一台打字机。

打字机可以创建一本书,但一次只能创建一页。现在,如果你只是从头开始,像 for 循环一样一次看一个,那么是的,这几乎就像阅读一本普通的书。

但与普通书不同的是,一旦打字机打完一页,你就不能倒退,那一页现在已经消失了。

我希望这是有道理的。

于 2012-11-21T14:43:41.680 回答
2

我试图找出一个更一般的答案:

  • 可迭代对象是可以迭代的对象。这些包括列表、元组等。根据要求,它们会提供一个迭代器。

  • 迭代器是用于迭代的对象。它为每个请求提供一个值,如果它结束了,它就结束了。这些是生成器、列表迭代器等,还有例如文件对象。每个迭代器都是可迭代的,并把自己作为它的迭代器。

例子:

a = []
b = iter(a)
print a, b # -> [] <listiterator object at ...>

如果你这样做

for i in a: ...

a 通过它的方法被请求一个迭代__iter__()器,然后这个迭代器被查询下一个元素,直到用完。这通过.next()(resp. __next__()in 3.x) 方法发生。

索引是完全不同的事情。如果对象没有.__iter__()方法,则可以通过索引进行迭代,因此每个可索引对象都是可迭代的,反之则不然。

于 2012-11-21T15:05:49.433 回答