为什么在Python文档中迭代器被认为是函数样式?

2024-06-14 02:21:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图理解迭代器。我注意到Python documentation认为迭代器是一个函数样式构造。我不太明白。在

迭代器内部有一个状态,这不是真的吗。所以当你调用it.__next__()时,你改变了迭代器的状态。据我所知,对象的变化状态不被认为是函数式的,因为函数式编程强调对象/闭包的不变性和组合能力。在

实际上,出现这个问题是因为我想编写一个Scheme过程/函数,它接受令牌并返回迭代器。 在

(define tokens->iterator
  (lambda ls
    (lambda ()
      (if (null? ls)
          '*eoi*
          (let ((tok (car ls)))
            (set! ls (cdr ls))
            tok)))))

注意我必须使用set!来改变ls,这就是我提出这个问题的方式。在

使用它, 在

^{pr2}$

为了测试它, 在

scheme@(guile-user)> (it)
$2 = 1
scheme@(guile-user)> (it)
$3 = +
scheme@(guile-user)> (it)
$4 = 2
scheme@(guile-user)> (it)
$5 = *eoi*
scheme@(guile-user)> (it)
$6 = *eoi*

为了好玩,我还将其翻译成Python: 在

def tokens_to_iterator(*tup):
    ls = list(tup)
    def iterator():
        if not ls:
            return "*eoi*"
        else:
            tok = ls.pop(0)
            return tok
    return iterator

类似地,pop()方法通过改变列表移除并返回第一个元素。在

使用它, 在

it = tokens_to_iterator(1, "+", 2)

为了测试它, 在

>>> it()
1
>>> it()
'+'
>>> it()
2
>>> it()
'*eoi*'
>>> it()
'*eoi*'

有人能澄清一下吗?顺便说一句,我使用的是python3和Guile-Scheme,以防有人有兴趣尝试这些示例。在


Tags: 对象lambda函数return状态itlsscheme
2条回答

你的观点很好。迭代器当然不是“纯功能的”,这个术语通常用来描述完全不使用变异的习惯用法。更宽泛的术语“functional”的定义更为宽松,它表示使用相对较少变异的程序,这些程序使用高阶和一级函数,而且可能最广泛的是,“使用看起来不像C的奇怪抽象。”

坦率地说,我认为我应该把迭代器称为函数迭代器。那就是:我同意你的观点。在

函数式的样式是作为一个整体处理数据列表,而不是一个可以随意更改的值集合。例如,如果您有一个数字列表,并且要更改第三个元素,则非功能性方法是直接更改它:

>>> lst = ["a", "b", "c", "d", "e"]
>>> lst[3] = "Z"
>>> lst
["a", "b", "c", "Z", "e"]

函数式方法是编写一个接受原始序列的函数,并返回一个包含所做更改的新列表,而原始列表保持不变。在

^{pr2}$

这两个迭代器都不是纯功能的,因为它们确实保持可变状态,尽管被视为黑匣子,但您可以在功能上使用它们,因为迭代器的用户不能直接影响该状态。在

纯函数迭代器是一个函数,它将list当前状态作为输入,并返回一个值一个新状态以传递给函数的下一个调用。在

>>> state = 0
>>> def it(lst, state):
...   if state is None:
...       return None
...   return lst[state], state + 1
...
>>> lst = ["a", "b", "c", "d", "e"]
>>> value, new_state = it(lst, state)
>>> value
'a'
>>> state, new_state
(0, 1)
>>> it(lst, new_state)
('b', 2)
>>> state, new_state
(0, 1)

相关问题 更多 >