【发布时间】:2016-10-28 02:51:10
【问题描述】:
让我们考虑一个文件:
$ echo -e """This is a foo bar sentence .\nAnd this is the first txtfile in the corpus .""" > test.txt
$ cat test.txt
This is a foo bar sentence .
And this is the first txtfile in the corpus .
当我想按字符读取文件时,我可以https://stackoverflow.com/a/25071590/610569:
>>> fin = open('test.txt')
>>> while fin.read(1):
... fin.seek(-1,1)
... print fin.read(1),
...
T h i s i s a f o o b a r s e n t e n c e .
A n d t h i s i s t h e f i r s t t x t f i l e i n t h e c o r p u s .
但是使用 while 循环可能看起来有点不合 Python。当我使用fin.read(1) 检查EOF 然后回溯以读取当前字节时。所以我可以做这样的事情How to read a single character at a time from a file in Python?:
>>> import functools
>>> fin = open('test.txt')
>>> fin_1byte = iter(functools.partial(fin.read, 1), '')
>>> for c in fin_1byte:
... print c,
...
T h i s i s a f o o b a r s e n t e n c e .
A n d t h i s i s t h e f i r s t t x t f i l e i n t h e c o r p u s .
但是当我在没有第二个参数的情况下尝试它时,它会抛出一个 TypeError:
>>> fin = open('test.txt')
>>> fin_1byte = functools.partial(fin.read, 1)
>>> for c in iter(fin_1byte):
... print c,
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'functools.partial' object is not iterable
iter 中的第二个参数是什么? 文档也没有说太多:https://docs.python.org/2/library/functions.html#iter 和 https://docs.python.org/3.6/library/functions.html#iter
根据文档:
返回一个迭代器对象。根据第二个参数的存在,第一个参数的解释非常不同。如果没有第二个参数,object 必须是支持迭代协议(iter() 方法)的集合对象,或者它必须支持序列协议(getitem()具有从 0 开始的整数参数的方法)。如果它不支持这些协议中的任何一个,则会引发 TypeError。如果给定第二个参数 sentinel,则 object 必须是可调用对象。在这种情况下创建的迭代器将在每次调用其 next() 方法时调用不带参数的对象;如果返回的值等于 sentinel,则会引发 StopIteration,否则将返回该值。
我猜文档需要一些“解密”:
- 如果没有第二个参数,对象必须是支持迭代协议(iter() 方法)的集合对象
这是否意味着它需要来自collections?还是说只要对象有__iter__()就可以了?
- ,或者它必须支持序列协议(getitem() 方法,整数参数从 0 开始)
这是相当神秘的。那么这是否意味着它试图查看序列是否被索引并因此可以查询并且索引必须从 0 开始?这是否也意味着索引需要是连续的,即 0, 1, 2, 3, ... 而不是 0, 2, 8, 13, ...?
- 如果它不支持其中任何一个协议,则会引发 TypeError。
是的,这部分,我明白了=)
- 如果给定第二个参数 sentinel,则 object 必须是可调用对象。
好的,现在这有点科幻了。将某些东西称为sentinel 只是 Python 中的一个术语吗? sentinel 在 Python 上是什么意思?而“可调用对象”就像它是一个函数而不是类型对象?
- 在这种情况下创建的迭代器将在每次调用其 next() 方法时调用不带参数的对象;
这部分我不太明白,也许举个例子会有所帮助。
- 如果返回值等于sentinel,StopIteration 将被引发,否则返回值。
好的,所以sentinel 这里指的是一些破坏标准?
有人可以帮助破译/澄清上述关于iter的观点的含义吗?
【问题讨论】:
-
在我看来,文档准确地解释了第二个参数是什么。解释从“如果给出第二个参数,哨兵,”开始,一直到段落的结尾。你没有得到什么?
-
文档很有用:iter
-
别管骗子的Java标签;它普遍适用。
-
如果@Antti 没有击中我的欺骗目标,你就会得到答案。我不知道他为什么这样做。
-
iter(func, sentinel)的第二种形式只是重复调用func()直到它返回sentinel然后iter()引发StopIteration。这意味着func()通常是有状态的或随机的。在您的示例中,fin.read将一次返回 1 个字符,并在到达文件末尾时返回空字符串''。
标签: python arguments iterable built-in