Skip to content

Commit 586b523

Browse files
committed
2.4.4
1 parent 84925ef commit 586b523

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

2.4.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,71 @@ True
272272
列表推导式使用序列的接口约定增强了数据处理的范式,因为列表是一种序列数据类型。
273273

274274
**扩展阅读。**Dive Into Python 3 的[推导式](http://diveintopython3.ep.io/comprehensions.html)一章包含了一些示例,展示了如何使用 Python 浏览计算机的文件系统。这一章介绍了`os`模块,它可以列出目录的内容。这个材料并不是这门课的一部分,但是推荐给任何想要增加 Python 知识和技巧的人。
275+
276+
**实现。**列表是序列,就像元组一样。Python 语言并不提供给我们列表实现的直接方法,只提供序列抽象,和我们在这一节介绍的可变方法。为了克服这一语言层面的抽象界限,我们可以开发列表的函数式实现,再次使用递归表示。这一节也有第二个目的:加深我们对调度函数的理解。
277+
278+
我们会将列表实现为函数,它将一个递归列表作为自己的局部状态。列表需要有一个身份,就像任何可变值那样。特别地,我们不能使用`None`来表示任何空的可变列表,因为两个空列表并不是相同的值(例如,向一个列表添加元素并不会添加到另一个),但是`None is None`。另一方面,两个不同的函数足以区分两个两个空列表,它们都将`empty_rlist`作为局部状态。
279+
280+
我们的可变列表是个调度函数,就像我们偶对的函数式实现也是个调度函数。它检查输入“信息”是否为已知信息,并且对每个不同的输入执行相应的操作。我们的可变列表可响应五个不同的信息。前两个实现了序列抽象的行为。接下来的两个添加或删除列表的第一个元素。最后的信息返回整个列表内容的字符串表示。
281+
282+
```py
283+
>>> def make_mutable_rlist():
284+
"""Return a functional implementation of a mutable recursive list."""
285+
contents = empty_rlist
286+
def dispatch(message, value=None):
287+
nonlocal contents
288+
if message == 'len':
289+
return len_rlist(contents)
290+
elif message == 'getitem':
291+
return getitem_rlist(contents, value)
292+
elif message == 'push_first':
293+
contents = make_rlist(value, contents)
294+
elif message == 'pop_first':
295+
f = first(contents)
296+
contents = rest(contents)
297+
return f
298+
elif message == 'str':
299+
return str(contents)
300+
return dispatch
301+
```
302+
303+
我们也可以添加一个辅助函数,来从任何内建序列中构建函数式实现的递归列表。只需要以递归顺序添加每个元素。
304+
305+
306+
```py
307+
>>> def to_mutable_rlist(source):
308+
"""Return a functional list with the same contents as source."""
309+
s = make_mutable_rlist()
310+
for element in reversed(source):
311+
s('push_first', element)
312+
return s
313+
```
314+
315+
在上面的定义中,函数`reversed`接受并返回可迭代值。它是使用序列的接口约定的另一个示例。
316+
317+
这里,我们可以构造函数式实现的列表,要注意列表自身也是个函数。
318+
319+
```py
320+
>>> s = to_mutable_rlist(suits)
321+
>>> type(s)
322+
<class 'function'>
323+
>>> s('str')
324+
"('heart', ('diamond', ('spade', ('club', None))))"
325+
```
326+
327+
另外,我们可以像列表`s`传递信息来修改它的内容,比如移除第一个元素。
328+
329+
```py
330+
>>> s('pop_first')
331+
'heart'
332+
>>> s('str')
333+
"('diamond', ('spade', ('club', None)))"
334+
```
335+
336+
原则上,操作`push_first``pop_first`足以对列表做任意修改。我们总是可以清空整个列表,之后将它旧的内容替换为想要的结果。
337+
338+
**消息传递。**给予一些时间,我们就能实现许多实用的 Python 列表可变操作,比如`extend``insert`。我们有一个选择:我们可以将它们全部实现为函数,这会使用现有的消息`pop_first``push_first`来实现所有的改变操作。作为代替,我们也可以向`dispatch`函数体添加额外的`elif`子句,每个子句检查一个消息(例如`'extend'`),并且直接在`contents`上做出合适的改变。
339+
340+
第二个途径叫做消息传递,它把数据值上面所有操作的逻辑封装在一个函数中,这个函数响应不同的消息。一个使用消息传递的程序定义了调度函数,每个函数都拥有局部状态,通过传递“消息”作为第一个参数给这些函数来组织计算。消息是对应特定行为的字符串。
341+
342+
可以想象,在`dispatch`的函数体中通过名称来枚举所有这些消息非常无聊,并且易于出现错误。Python 的字典提供了一种数据类型,会帮助我们管理消息和操作之间的映射,它会在下一节中介绍。

0 commit comments

Comments
 (0)