Python 中是否有没有长度的相关迭代器?
Are there relevant iterables with no length in Python?
在 Luciano Ramalho 的 Fluent Python 中,可迭代对象被定义为一个对象,其中实现了 __iter__
方法,没有额外的特征。
我目前正在为外行编写一个教程,我试图在其中分块 Python 的核心概念,以使编程对于新手来说更易于管理。
当我将这些对象与“大小”的概念相关联时,我发现向这些人解释可迭代对象及其效用会更容易(因此也是 length
)。通过说“可迭代对象是具有长度的对象”并因此与 len
函数联系起来,我能够自然地发展出循环和迭代的概念以及标准库 list
等常用类型, dict
, tuple
, str
, 以及 numpy.ndarray
, pandas.Series
和 pandas.DataFrame
.
但是,由于现在我知道了 __iter__
方法的唯一必要性,所以在某些情况下,与 len
的类比可能会失败。 Ramalho甚至在他的书中提供了一个即兴的example:
import re
import reprlib
RE_WORD = re.compile(r'\w+')
class Sentence:
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
正如预期的那样,Sentence
的任何实例都是可迭代的(我可以使用 for
循环),但是 len(Sentence('an example'))
会引发 TypeError
.
由于上述所有对象都是可迭代对象和实现了__len__
方法,我想知道Python中是否有相关对象是可迭代对象 (__iter__
),但没有长度 (__len__
),所以如果我能确定我是只是在我的教程中添加一个脚注,还是想出一个不同的类比。
一个文件没有长度:
>>> with open("test") as f:
... print(len(f))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type '_io.TextIOWrapper' has no len()
像 open 中那样遍历文件遍历行,即由换行符分隔的文本块。要知道有多少行,必须完整读取文件然后遍历 - 根据文件的大小,这可能需要很长时间,或者计算机可能 运行 内存不足。
迭代器是无处不在的迭代器,通常不提供长度:
>>> len(iter('foo'))
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
len(iter('foo'))
TypeError: object of type 'str_iterator' has no len()
>>> len(iter((1, 2, 3)))
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
len(iter((1, 2, 3)))
TypeError: object of type 'tuple_iterator' has no len()
>>> len(iter([1, 2, 3]))
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
len(iter([1, 2, 3]))
TypeError: object of type 'list_iterator' has no len()
在 Luciano Ramalho 的 Fluent Python 中,可迭代对象被定义为一个对象,其中实现了 __iter__
方法,没有额外的特征。
我目前正在为外行编写一个教程,我试图在其中分块 Python 的核心概念,以使编程对于新手来说更易于管理。
当我将这些对象与“大小”的概念相关联时,我发现向这些人解释可迭代对象及其效用会更容易(因此也是 length
)。通过说“可迭代对象是具有长度的对象”并因此与 len
函数联系起来,我能够自然地发展出循环和迭代的概念以及标准库 list
等常用类型, dict
, tuple
, str
, 以及 numpy.ndarray
, pandas.Series
和 pandas.DataFrame
.
但是,由于现在我知道了 __iter__
方法的唯一必要性,所以在某些情况下,与 len
的类比可能会失败。 Ramalho甚至在他的书中提供了一个即兴的example:
import re
import reprlib
RE_WORD = re.compile(r'\w+')
class Sentence:
def __init__(self, text):
self.text = text
def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text)
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
正如预期的那样,Sentence
的任何实例都是可迭代的(我可以使用 for
循环),但是 len(Sentence('an example'))
会引发 TypeError
.
由于上述所有对象都是可迭代对象和实现了__len__
方法,我想知道Python中是否有相关对象是可迭代对象 (__iter__
),但没有长度 (__len__
),所以如果我能确定我是只是在我的教程中添加一个脚注,还是想出一个不同的类比。
一个文件没有长度:
>>> with open("test") as f:
... print(len(f))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type '_io.TextIOWrapper' has no len()
像 open 中那样遍历文件遍历行,即由换行符分隔的文本块。要知道有多少行,必须完整读取文件然后遍历 - 根据文件的大小,这可能需要很长时间,或者计算机可能 运行 内存不足。
迭代器是无处不在的迭代器,通常不提供长度:
>>> len(iter('foo'))
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
len(iter('foo'))
TypeError: object of type 'str_iterator' has no len()
>>> len(iter((1, 2, 3)))
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
len(iter((1, 2, 3)))
TypeError: object of type 'tuple_iterator' has no len()
>>> len(iter([1, 2, 3]))
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
len(iter([1, 2, 3]))
TypeError: object of type 'list_iterator' has no len()