为何可遍历非迭代器对象?(以spaCy Doc对象为例)
为何可遍历非迭代器对象?(以spaCy Doc对象为例)
哈哈,这个问题我刚啃Python迭代相关知识的时候也踩过坑!其实核心就是得把**可迭代对象(iterable)和迭代器(iterator)**这俩玩意儿给掰扯清楚——很多刚接触的朋友都会把它们混为一谈~
先看你遇到的情况:你用for token in doc:的时候能顺顺当当遍历每个词,但直接调用next(doc)就报错,对吧?这完全正常,因为spaCy的Doc对象是可迭代对象,但不是迭代器。
给你掰碎了说:
- 可迭代对象:只要实现了
__iter__()方法的对象都算。当你用for循环遍历它的时候,Python会自动帮你做一件事:先调用iter(doc),把这个可迭代对象转换成一个迭代器,然后再不断调用这个迭代器的__next__()方法来逐个取元素,直到取完抛出StopIteration异常,循环就自动停了。这就是为啥你能遍历Doc里的每个Token。 - 迭代器:得同时实现
__iter__()和__next__()方法,而且__iter__()返回的是它自己。只有这种对象,你才能直接用next()函数去调用它,每次拿一个元素。
你可以自己验证一下(在Python交互环境里敲就行):
>>> from collections.abc import Iterable, Iterator >>> import spacy >>> nlp = spacy.load("en_core_web_sm") >>> doc = nlp("Berlin looks like a nice city") >>> isinstance(doc, Iterable) # 检查是不是可迭代对象 True >>> isinstance(doc, Iterator) # 检查是不是迭代器 False
那如果你非要用next()来逐个取Doc里的元素怎么办?简单,先把它转成迭代器就行:
>>> doc_iterator = iter(doc) >>> next(doc_iterator) # 这时候就会返回第一个Token:Berlin >>> next(doc_iterator) # 接着是looks
说白了,可迭代对象就像一个装着东西的盒子,你得先拿个“取物器”(迭代器)才能逐个掏里面的东西;而迭代器本身就是那个“取物器”,能直接上手掏。spaCy的Doc就是那个盒子,所以你得先通过iter()拿到取物器,才能用next()来取东西~
内容来源于stack exchange
相关产品推荐
相关产品推荐

