为什么迭代器在 Python 文档中被认为是函数式的?
Why iterator is considered functional-style in the Python documentation?
我正在尝试了解迭代器。我注意到 Python documentation 认为迭代器是一种函数式结构。不是很懂
迭代器里面不是有状态吗。所以当你调用 it.__next__()
时,你改变了迭代器的状态。据我所知,对象的变异状态不被认为是函数式的,因为函数式编程强调 object/closure.
的不变性和可组合性
实际上,问题的出现是因为我想写一个 Scheme procedure/function 它接受令牌和 return 一个迭代器。
(define tokens->iterator
(lambda ls
(lambda ()
(if (null? ls)
'*eoi*
(let ((tok (car ls)))
(set! ls (cdr ls))
tok)))))
注意我必须使用 set!
来变异 ls
,这就是我想出这个问题的方式。
要使用它,
(define it (tokens->iterator 1 '+ 2))
为了测试它,
scheme@(guile-user)> (it)
= 1
scheme@(guile-user)> (it)
= +
scheme@(guile-user)> (it)
= 2
scheme@(guile-user)> (it)
= *eoi*
scheme@(guile-user)> (it)
= *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() 方法通过改变列表删除并 return 第一个元素。
要使用它,
it = tokens_to_iterator(1, "+", 2)
为了测试它,
>>> it()
1
>>> it()
'+'
>>> it()
2
>>> it()
'*eoi*'
>>> it()
'*eoi*'
谁能澄清一下?顺便说一句,我正在使用 Python 3 和 Guile Scheme,以防有人有兴趣尝试这些示例。
你说得很好。迭代器当然不是 "purely functional," 这个经常用来描述完全不使用变异的习语的术语。不过,更广泛的术语 "functional," 的定义更为宽松,以表示使用相对较少变异的程序,这些程序使用高阶和第一个 class 函数,也许最广泛的是,"use weird abstractions that don't look like C."
我认为,坦率地说,我不会称迭代器为函数式。那就是:我同意你的看法。
函数式 风格 是将数据列表作为一个整体来处理,而不是您可以随心所欲更改的值集合。例如,如果你有一个数字列表,你想改变第 3 个元素,非功能性的方法是直接改变它:
>>> lst = ["a", "b", "c", "d", "e"]
>>> lst[3] = "Z"
>>> lst
["a", "b", "c", "Z", "e"]
函数式方法是编写一个函数,该函数采用原始序列和return经过更改的新列表,保持原始序列不变。
>>> lst = ["a", "b", "c", "d", "e"]
>>> new_lst = [x if i != 3 else "Z" for (i, x) in enumerate(lst)]
>>> lst
["a", "b", "c", "d", "e"]
>>> new_lst
["a", "b", "c", "Z", "e"]
你的迭代器都不是纯功能的,因为它们确实保持可变状态,虽然被视为黑盒子,但你可以在功能上使用它们,因为迭代器的 user 不能影响它直接说。
一个纯函数迭代器是一个函数,它将列表和当前状态作为输入,return一个值和 传递给下一次函数调用的新状态。
>>> 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)
我正在尝试了解迭代器。我注意到 Python documentation 认为迭代器是一种函数式结构。不是很懂
迭代器里面不是有状态吗。所以当你调用 it.__next__()
时,你改变了迭代器的状态。据我所知,对象的变异状态不被认为是函数式的,因为函数式编程强调 object/closure.
实际上,问题的出现是因为我想写一个 Scheme procedure/function 它接受令牌和 return 一个迭代器。
(define tokens->iterator
(lambda ls
(lambda ()
(if (null? ls)
'*eoi*
(let ((tok (car ls)))
(set! ls (cdr ls))
tok)))))
注意我必须使用 set!
来变异 ls
,这就是我想出这个问题的方式。
要使用它,
(define it (tokens->iterator 1 '+ 2))
为了测试它,
scheme@(guile-user)> (it)
= 1
scheme@(guile-user)> (it)
= +
scheme@(guile-user)> (it)
= 2
scheme@(guile-user)> (it)
= *eoi*
scheme@(guile-user)> (it)
= *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() 方法通过改变列表删除并 return 第一个元素。
要使用它,
it = tokens_to_iterator(1, "+", 2)
为了测试它,
>>> it()
1
>>> it()
'+'
>>> it()
2
>>> it()
'*eoi*'
>>> it()
'*eoi*'
谁能澄清一下?顺便说一句,我正在使用 Python 3 和 Guile Scheme,以防有人有兴趣尝试这些示例。
你说得很好。迭代器当然不是 "purely functional," 这个经常用来描述完全不使用变异的习语的术语。不过,更广泛的术语 "functional," 的定义更为宽松,以表示使用相对较少变异的程序,这些程序使用高阶和第一个 class 函数,也许最广泛的是,"use weird abstractions that don't look like C."
我认为,坦率地说,我不会称迭代器为函数式。那就是:我同意你的看法。
函数式 风格 是将数据列表作为一个整体来处理,而不是您可以随心所欲更改的值集合。例如,如果你有一个数字列表,你想改变第 3 个元素,非功能性的方法是直接改变它:
>>> lst = ["a", "b", "c", "d", "e"]
>>> lst[3] = "Z"
>>> lst
["a", "b", "c", "Z", "e"]
函数式方法是编写一个函数,该函数采用原始序列和return经过更改的新列表,保持原始序列不变。
>>> lst = ["a", "b", "c", "d", "e"]
>>> new_lst = [x if i != 3 else "Z" for (i, x) in enumerate(lst)]
>>> lst
["a", "b", "c", "d", "e"]
>>> new_lst
["a", "b", "c", "Z", "e"]
你的迭代器都不是纯功能的,因为它们确实保持可变状态,虽然被视为黑盒子,但你可以在功能上使用它们,因为迭代器的 user 不能影响它直接说。
一个纯函数迭代器是一个函数,它将列表和当前状态作为输入,return一个值和 传递给下一次函数调用的新状态。
>>> 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)