问题 在Python中“消费”是什么意思?在迭代器中?


我已经在Python工作了几个月了,我发现我经常忽略乍看之下逃避我的词汇,而不是试图获得一个想法的要点。现在,回想起来,我仍然发现自己对这个词的含义感到困惑 消耗 是指。我最初的兴趣来自迭代器的解释,它说明了迭代器的消耗价值。但是,环顾四周,这在Python词典中似乎并不常见。或者是吗?在这里挖掘主要发现Web服务的引用,以及关于如何隐藏函数或结果的一两个讨论。

我想那时,把我的无知分解为几个基点:

  1. “消费”在不同的Pythonic环境中做不同的事情吗?
  2. 数据被消耗时会发生什么,例如 iter()
  3. 当一个变量被赋给迭代器的结果 - 据称消耗的数据 - 它是否不再属于迭代器?
  4. 在对迭代器的单次调用中,您是否可以从迭代器对象中使用多个值?

我希望这有点道理。请注意,这不涉及任何特定需要;我只是混淆了理性的合理性。

编辑:还有一件事......做一个迭代的值(当调用时 next()留在记忆中?


2142
2018-03-03 22:32


起源

你在哪里读到这个? - Felix Kling
你指的是什么部分? - Nathanus
我的意思是,这个词在哪里 消耗 用来。一个链接会很好(我发现的唯一参考是在 itertools 文档)。 - Felix Kling
doughellmann.com/PyMOTW/itertools ---“由于tee()创建的新迭代器共享输入,因此不应再使用原始迭代器。如果消耗了原始输入的值,则新迭代器将不会生成这些值:” - Nathanus
在C#WPF文章中也有很多“消费”。


答案:


关于2。

事实上,我们必须区分两个案例。

还记得Greg Hewgill写的:

“迭代器”是一个负责的单个对象   用于创建一些元素序列。   此序列可能是现有列表的元素,   或者它可能是计算的东西,如素数   或π的十进制数字。

第一个案例

迭代器计算受刺激时必须产生的对象;也就是说,在调用之前,生成的对象不存在 next() 。因此,如果为对象分配了名称,则后者将存活;如果没有,该对象将在某个时间内没有被绑定到命名空间中的名称而存在,然后它将在存储器中消失,也就是说它占据的位将在稍后或更早用于另一个对象。

第二种情况 

是迭代器返回以前存在的属于列表,元组,字典等的对象。在这种情况下,每个对象产生一个 next() 已经绑定了一个名字。然后,如果在从迭代器“弹出”对象时将对象分配给新名称,则会有两个绑定到对象的名称。如果对象未分配给名称,它将继续绑定到只有一个名称,足以维持对象的活动。

共同点:

每次通过调用迭代器生成对象时,如果没有为其分配名称,则操作的唯一结果是迭代器已被“消耗”。可以这样说,即使在生成对象之后没有永久性后果,也会发生一些让迭代器内部产生痕迹的东西。

人们谈到在为对象分配名称时使用迭代器,但是,我不想混淆。

注意:

实际上,如果某个对象预先存在于列表中,那么可能是它没有名称。但是列表中包含它“包含”的每个对象的引用......事实上,列表不是“包含”对象,而只是对对象的引用......这超出了我想说的范围。

关于3

你不应该写3: “当变量分配给......时”

这个单词 变量 是Python的一个陷阱,因为它有一个模棱两可的含义。没有 变量 在Python中,在其他语言中已知的常识中,也就是说a «值可以改变的记忆的分隔部分»。 只有对象。这个单词 变量 习惯用来表示一个 识别码。因此,调用它是一种更好的做法 识别码, 要么 名称。这避免了混淆。

关于4

我不认为只有一次调用就可以从迭代器获得两次返回 next()


4
2018-03-04 00:39



很棒的解释,以及完整的。非常棒。 :) - Nathanus
“Python中没有变量”:这真的没有用。 “在其他语言中已知的常识”中,您的意思是“在C中”。许多语言都像Python一样工作,调用变量在所有这些变量中都非常有意义。 - Ned Batchelder
@Ned Batchelder虽然,对我来说理解Python的数据模型是基于对象而不是变量是非常有帮助的。我不是唯一理解这一点的人。 - 如果其他语言作为Python工作,则不能证明Python有变量。相反,这意味着这些其他语言没有变量。顺便问一下,这些其他语言是什么? - eyquem
其他语言是PHP,Ruby,Lisp,Perl等。它们都有变量。这些变量是可以引用值的名称。变量是其值可以的名称 变化 随着时间的推移。 C的做法与Python不同。这并不意味着Python没有变量。 - Ned Batchelder


术语“使用”是一个非正式术语,指的是迭代器在Python中的工作方式。 “迭代器”是一个负责创建一些元素序列的单个对象。此序列可能是现有列表的元素,也可能是计算的值,如素数或π的十进制数字。

当调用者从迭代器请求“下一个”项时,迭代器提供下一个项,然后更改其自己的状态,以便在此之后生成下一个项。这通常是你所期望的。

如果我有一个产生增加素数序列的发生器,我第一次调用它时会得到2作为回报。下一次,我会得到3.如果我然后给你一个对该生成器的引用,你会调用它(因为你认为是第一次)并得到5.没有任何方法可以“重置”生成器,所以它将再次从2开始,除非创建一个全新的生成器实例。在那种情况下,我可以说我已经 消费 在给你发电机之前的前两项。


5
2018-03-03 23:02



因此,在迭代器对象的情况下,使用值就像 .pop()它从顶部?如果你愿意,从卡座上取出卡? - Nathanus
是的,这是思考它的一种方式。但是,请注意列表上的迭代器不会 修改 清单本身。迭代器是一个独立的对象,按顺序生成列表的元素。 - Greg Hewgill
这是一个困难的概念,我还没有完全理解它的所有细节。但是你成功地给出了清晰而可靠的解释。 +1 - eyquem


我不是Python专家,但我可以这样说:大多数时候,编程中的消耗与生产相反。您可以将某些流程分类为生产者,从而创建价值;和其他人作为消费者,使用生产者创造的价值观。

在迭代器的情况下,迭代器是一个生成器,它通过一个可迭代的对象并按顺序“生成”每个值,一次一个。从迭代器“消耗”数据只是意味着使用它。


4
2018-03-03 22:39



另外:生产者的另一个词是“发电机”;在Python中,恰好引用了一种特定的操作。 :-) - Platinum Azure
Greg Hewgill的回答比我的回答更有用,更有用。我只是在很高的层次上回答这个问题。 - Platinum Azure


迭代器 只是支持这些方法的对象 __iter__ 和 next。迭代器的一般用例是遍历它们,其中每次循环都是结果 iterator.next() 将被分配给变量。

考虑到这一点,打电话给 iterator.next() 可以被称为“消费价值”,因为一般来说是一种呼唤 next更改迭代器的状态,并且无法返回到先前的状态。

但是,没有什么能阻止迭代器重复返回相同的值,甚至提供回滚到先前状态的方法。在这些情况下,使用“消费”一词可能不适用。

至于迭代器返回的数据会发生什么 next 方法,它完全依赖于迭代器的实现。生成器倾向于丢弃它们产生的结果,但是如果容器也是迭代器,那么数据返回时 next() 被调用仍将存在于容器对象中。


1
2018-03-04 00:32





我可以回答你的第一点,消耗是耗尽一个迭代,这意味着运行下一个项目的可迭代。


0
2018-03-03 22:39





“消费”在不同的Pythonic环境中做不同的事情吗?

不,“消费”总是做同样的事情。

消费时数据会发生什么变化,例如在iter()中?

它从您获得它的地方不再可用。

当一个变量被赋给迭代器的结果 - 据称消耗的数据 - 它是否不再属于迭代器?

正确。迭代器生成数据后,数据就不再属于迭代器。

在对迭代器的单次调用中,您是否可以从迭代器对象中使用多个值?

通常,没有。但是,您可以编写一个自定义迭代器,一次生成多个值。


0
2018-03-25 01:42