Python 中 iter 函数的第二个参数是什么?

2024-05-01

让我们考虑一个文件:

$ 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 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,然后回溯以读取当前字节。所以我可以做这样的事情如何在Python中一次读取一个文件中的一个字符? https://stackoverflow.com/q/2988211/610569:

>>> 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/2/library/functions.html#iter and https://docs.python.org/3.6/library/functions.html#iter https://docs.python.org/3.6/library/functions.html#iter


根据文档:

返回一个迭代器对象。根据第二个参数的存在,第一个参数的解释非常不同。如果没有第二个参数,object 必须是支持迭代协议的集合对象(iter() 方法),或者必须支持序列协议(getitem() 方法,整数参数从 0 开始)。如果它不支持这些协议中的任何一个,则会引发 TypeError。如果给出第二个参数哨兵,则对象必须是可调用对象。在这种情况下创建的迭代器将在每次调用对象时调用不带参数的对象next() 方法;如果返回的值等于sentinel,则将引发StopIteration,否则将返回该值。

我猜文档需要一些“解密”:

  • 如果没有第二个参数,object 必须是支持迭代协议的集合对象(iter() 方法)

这是否意味着它需要来自collections?或者说只要该物体有一个__iter__(), 没关系?

  • ,或者它必须支持序列协议(getitem() 方法,整数参数从 0 开始)

那就比较隐晦了。那么这是否意味着它会尝试查看序列是否已建立索引并因此可查询,并且索引必须从 0 开始?这是否也意味着索引需要是连续的,即 0、1、2、3...,而不是 0、2、8、13... 之类的?

  • 如果它不支持这些协议中的任何一个,则会引发 TypeError。

是的,这部分我明白=)

  • 如果给出第二个参数哨兵,则对象必须是可调用对象。

好吧,现在这有点科幻了。将某物称为“a”只是 Python 中的一个术语吗?sentinel?什么是sentinel意思是Python方式吗?和“可调用对象”一样,它是一个函数而不是类型对象?

  • 在这种情况下创建的迭代器将在每次调用其 next() 方法时调用不带参数的对象;

这部分我不太明白,也许一个例子会有所帮助。

  • 如果返回的值等于sentinel,则将引发StopIteration,否则将返回该值。

可以,然后呢sentinel这里指的是一些突破标准?

有人可以帮助破译/澄清上述几点的含义吗iter?


只要有一个论点,iter必须给出一个具有以下特征的对象__iter__特殊方法,or __getitem__特殊方法。如果它们都不存在,iter will提出错误

>>> iter(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not iterable

有 2 个迭代协议。旧协议依赖于调用__getitem__对于从 0 到 1 的连续整数IndexError。新协议依赖于从返回的迭代器__iter__.

在Python 2中,str甚至没有__iter__特殊方法:

Python 2.7.12+ (default, Sep 17 2016, 12:08:02) 
[GCC 6.2.0 20160914] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'abc'.__iter__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__iter__'

但它仍然是可迭代的:

>>> iter('abc')
<iterator object at 0x7fcee9e89390>

为了使您的自定义类可迭代,您需要either __iter__ or __getitem__这引发了IndexError对于不存在的项目:

class Foo:
    def __iter__(self):
        return iter(range(5))

class Bar:
    def __getitem__(self, i):
        if i >= 5:
            raise IndexError
        return i

使用这些:

>>> list(iter(Foo()))
[0, 1, 2, 3, 4]
>>> list(iter(Bar()))
[0, 1, 2, 3, 4]

通常是明确的iter不需要,因为for期望的循环和方法可迭代对象将隐式创建一个迭代器:

>>> list(Foo())
[0, 1, 2, 3, 4]
>>> for i in Bar():
0
1
2
3
4

对于 2 参数形式,第一个参数必须是实现__call__。第一个参数在没有参数的情况下被调用;返回值是从迭代器产生的。当该迭代中函数调用返回的值等于给定值时,迭代停止sentinel值,就好像:

value = func()
if value == sentinel:
    return
else:
    yield value

例如,获取骰子上的值before我们扔 6 个,

>>> import random
>>> throw = lambda: random.randint(1, 6)
>>> list(iter(throw, 6))
[3, 2, 4, 5, 5]
>>> list(iter(throw, 6))
[1, 3, 1, 3, 5, 1, 4]

为了进一步澄清,给定的函数(或给定的对象)__call__特殊方法)在每次调用时不带参数next()用在迭代器上:

>>> def throw_die():
...     die = random.randint(1, 6)
...     print("returning {}".format(die))
...     return die
...
>>> throws = iter(throw_die, 6)
>>> next(throws)
returning 2
2
>>> next(throws)
returning 4
4
>>> next(throws)
returning 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

(i.e. throw被称为throw()如果返回值不等于 6,则返回)。

或者在以下情况下

>>> fin_1byte = iter(functools.partial(fin.read, 1), '')
>>> for c in fin_1byte:
...     print c,

从文件末尾读取文件返回空字符串(如果是二进制文件,则为空字节):

>>> from io import StringIO
>>> fin = StringIO(u'ab')
>>> fin.read(1)
u'a'
>>> fin.read(1)
u'b'
>>> fin.read(1)
u''

如果尚未到达文件末尾,则返回一个字符。

这也可用于通过重复的函数调用创建无限迭代器:

>>> dice = iter(throw, 7)

由于返回的值永远不可能等于 7,因此迭代器将永远运行。一个常见的习惯用法是使用匿名object确保对于任何可以想象的值,比较都不会成功

>>> dice = iter(throw, object())

Because

>>> object() != object()
True

注意,这个词sentinel通常用于在某些数据中用作结束标记的值,并且该值不会在数据中自然出现,如这个Java答案 https://stackoverflow.com/questions/21666508/can-someone-explain-to-me-what-a-sentinel-does-in-java-or-how-it-works.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中 iter 函数的第二个参数是什么? 的相关文章

随机推荐

  • 多态性和数组指针[重复]

    这个问题在这里已经有答案了 我有一个A类 class A public virtual double getValue 0 还有B类 class B public A public virtual double getValue retur
  • 函数默认参数有些问题?

    看到这个 let foo outer function bar func x gt foo let foo inner console log func bar outer 我想知道为什么输出是 外部 而不是 内部 我知道 JavaScri
  • 在不同的 PC 之间传输 Python 设置

    我的情况是我有两台笔记本电脑fresh installation of windows 现在我用它们来编程 所以 假设我在一台笔记本电脑上安装了各种 python 模块 包 那么我有什么办法可以clone我的另一台笔记本电脑上的完整 pyt
  • ValueError:BitVect 的长度必须相同(rdkit)

    我正在计算 2 个摩尔之间的结构相似性概况rdkit 当我在 google colab 中运行程序时 rdkit 2020 09 2 python 3 7 程序运行良好 当我在 PC 上运行时出现错误 rdkit 2021 03 2 pyt
  • Cloudformation 模板 - 具有 cloudfront 分发的 S3 存储桶网站 - 分发无法访问源

    我只是想在 S3 存储桶上获取一个静态站点 并且只能通过 CloudFront 发行版访问它 但是缺少一些东西 我不知道是什么 目前我的堆栈有 用于站点托管的 S3 存储桶 用于为站点提供服务的云前端发行版 存储桶策略 仅允许分配访问该存储
  • AJAX 以渐进方式读取数据,而不仅仅是在完成时读取数据

    我喜欢为我的 ajax 调用创建一个进度条 为此 我可以使我的服务器端脚本返回其进度状态 所以我需要 JavaScript 来读取这个进度级别并显示它 有可能吗还是我走错了路 你可以尝试这样的事情 一些伪代码 假设是 jQuery 因为你已
  • 如何以编程方式将数据写入Azure Blob存储?

    我正在使用下面的 PowerShell 脚本通过 REST API 调用从源读取 JSON 数据 现在我想将 Result 的数据加载到 Azure Blob 存储中 有什么想法吗 Params URI https 3ea5e53b 817
  • Apache:配置应用程序侦听器时出错

    当我尝试运行该应用程序时 我遇到了这个问题 警告 SetContextPropertiesRule Context 设置属性 源 到 org eclipse jst j2ee server CongressApp 没有找到匹配的 财产 20
  • 运行时签名是什么?

    当涉及到有界类型时 我对 Java 的类型擦除有一些理解上的问题 考虑一下 class Event From the API class FooEvent extends Event abstract class Foo
  • 带参数的多重继承

    我已经阅读了很多有关继承的内容 但我似乎无法理解为什么这会给我一个错误 使用Python 2 7 x class A object def init self value super A self init print First s va
  • 是否可以使用 jQuery 从 SQL Server 检索数据?

    是否可以使用 jQuery 从 SQL Server 检索数据并使用 HTML 控件显示数据 jQuery 被设计为在浏览器环境中运行 所以这是一个具有 DOM 的环境 具有 JavaScript 支持 显然 等等 要从 MS SQL Se
  • 将参数内的日期转换为整数

    现在我有一个存储过程 它将日期作为integer 140213 但在SSRS我需要转换在date parameter to the integer前面提到过 现在我试图通过两个参数 日期和转换 来实现这一目标 一个参数允许您选择日期 第二个
  • 如何在本机反应中获取元素的宽度?

    如何获取 React Native 中元素的宽度 例如 View 由于React Native中没有宽度的百分比使用 如何获取元素或父元素的宽度 您可以致电onLayout测量元素的事件 measureView event console
  • 如何动态添加JSF组件

    我可以动态添加 JSF 组件吗 我需要一个带有按钮的表单 该按钮应该添加一个
  • NSFetchRequest 不返回任何内容

    任何人都可以发现为什么这不返回任何 ManagedObjects 吗 我试图将以下内容添加到 ATNSManagedObject EasyFetching 类中 但获取结果不返回任何内容 如果我在 EasyFetch 类之外获取这些对象 我
  • PL/SQL 中是否有方法将文本转换/编码为 XML 兼容文本?

    我的一位同事需要将 PL SQL 方法中的文本转换为符合 XML 的文本 因为他正在通过更新文本模板来构建 Excel 电子表格 PL SQL 中是否有方法将文本转换 编码为 XML 兼容文本 好吧 如果您只想转换 XML 字符 您需要执行
  • Django 信号发射一次,接收两次——为什么?

    我正在使用 Django 信号 但即使发出一次 它们似乎也会被接收两次 这是我正在使用的代码 这是一个将 Uploadify 与 Django 结合使用的简单包装器 Signal emitting code emits whenever a
  • RAILS 3 模型验证包含不起作用

    Schema Information Schema version Table name terms id integer not null primary key user id integer term type string 255
  • 是否可以将 Firebase 与 Windows 8 应用结合使用?

    我希望在使用 WinJS 制作的 Windows 8 应用程序中使用 Firebase 以下是我尝试写入 Firebase 根目录的方式 var dataRef new Firebase https
  • Python 中 iter 函数的第二个参数是什么?

    让我们考虑一个文件 echo e This is a foo bar sentence nAnd this is the first txtfile in the corpus gt test txt cat test txt This i