【问题标题】:How to use python iterators in a pure functional workflow如何在纯函数式工作流中使用 python 迭代器
【发布时间】:2020-10-29 21:59:15
【问题描述】:

困扰我的是,python 迭代器不属于纯不可变对象的定义,因为重新访问它们会修改它们的行为。 我了解它的工作方式,但使用迭代器阅读代码可能会变得混乱,而且看起来不是很 Python。

我的问题是......有没有一种很好的 Pythonic 方法来解决这个问题?

即此处使用迭代器会产生副作用(修改输入参数)使函数不纯

def foo(i):
    return list(i)
b = iter([1,2,3])
print(foo(b)) # outputs [1,2,3]
print(foo(b)) # outputs [] 
print(list(b)) # outputs []

【问题讨论】:

  • 你可以制作自己的持久化生成器,前提是你愿意失去原生类型的特性。 FP 利用 corecursion 来获得类似迭代器的行为。为了让 corecursion 在无限数据结构上工作,虽然需要惰性。我不知道如何用 python 来表达这一点,但在 JS 中有惰性对象获取器来拯救。这是一个 persistent iterator based on corecursion 的小 JS 草图,您可能希望将其转换为 python。

标签: python functional-programming semantics


【解决方案1】:

您的示例中的问题是您的迭代器 a 状态处于全局范围内,这已经与“无副作用”规则发生冲突。一旦它耗尽(例如,它抛出了 StopIteration 异常),它就完成了并且必须重新初始化。

from copy import copy
def foo(i):
    return list(i)

a = [1,2,3]
b = iter(a)
print(foo(copy(b))) # outputs [1,2,3]
print(foo(copy(b))) # outputs [1,2,3]
print(list(copy(b))) # outputs [1,2,3]

【讨论】:

  • 感谢您的发现!我已经更新了示例代码。 (foo方法中的'a'应该是'i')
  • 您的更改不会改变任何内容,您将相同的迭代器传递给foo() 的两个调用。也许我并不清楚指出一旦你创建了迭代器,它就会在自己内部保持自己的状态。因此,一旦迭代器用尽,就不会产生相同的结果。好吧,你可以说迭代器在你使用它的方式上并不纯粹。
  • 这主要是迭代器的设计和/或因为在这种情况下,迭代器是“作为参考”传递的。为了避免这种情况。请参阅我添加的模仿您的示例..
猜你喜欢
  • 2020-03-09
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
相关资源
最近更新 更多