forked from moyin/fzu-product
style: html to md syntax
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# CS61A Sec1
|
||||
|
||||
<strong>观前须知:</strong>
|
||||
**观前须知:**
|
||||
|
||||
本章节内容基于 Berkeley 大学的教材 [Composing Programs](http://www.composingprograms.com/) by [John DeNero](http://www.denero.org/),并在此基础上做了部分修改,是在[知识共享协议](https://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh)下所许可的。
|
||||
|
||||
@@ -28,7 +28,7 @@ from urllib.request import urlopen
|
||||
|
||||
这个 Python 代码是一个导入语句,加载了在互联网上访问数据的功能。实际上,它提供了一个叫做 urlopen 的函数,它可以在一个[统一资源定位符(URL)](https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL)上访问内容,可以通过它来访问互联网上的数据。
|
||||
|
||||
<strong>语句和表达式</strong>
|
||||
**语句和表达式**
|
||||
|
||||
Python 代码由语句和表达式组成。大体上,计算机程序由以下指令组成
|
||||
|
||||
@@ -37,7 +37,7 @@ Python 代码由语句和表达式组成。大体上,计算机程序由以下
|
||||
|
||||
语句通常描述行动;当 Python 解释器执行一个语句时,它执行相应的动作。另一方面,表达式通常描述的是计算;当 Python 评估一个表达式时,它计算该表达式的值。在这篇文章下,介绍了几种类型的声明和表达方式。
|
||||
|
||||
<strong>赋值语句</strong>
|
||||
**赋值语句**
|
||||
|
||||
```python
|
||||
shakespeare = urlopen('http://www.composingprograms.com/shakespeare.txt')
|
||||
@@ -47,7 +47,7 @@ shakespeare = urlopen('http://www.composingprograms.com/shakespeare.txt')
|
||||
|
||||
将变量名 `shakespeare` 用 `=` 和后面的表达式的值联系起来。该表达式将 `urlopen` 函数应用于一个 URL,该 URL 包含威廉 - 莎士比亚 37 部戏剧的完整文本,全部保存在一个文本文件中。
|
||||
|
||||
<strong>函数</strong>
|
||||
**函数**
|
||||
|
||||
函数封装了操作数据的逻辑。
|
||||
|
||||
@@ -64,7 +64,7 @@ shakespeare = urlopen('http://www.composingprograms.com/shakespeare.txt')
|
||||
|
||||
你可能不了解 `urlopen` 这个函数背后的逻辑,但这不影响你去调用这个函数,这就是函数封装的好处之一。
|
||||
|
||||
<strong>因此,函数是本章节关注的重点。</strong>
|
||||
**因此,函数是本章节关注的重点。**
|
||||
|
||||
我们来看另一个赋值语句:
|
||||
|
||||
@@ -74,7 +74,7 @@ words = set(shakespeare.read().decode().split())
|
||||
|
||||
这个语句将名字词与莎士比亚戏剧中出现的所有出现过的词(重复出现的词只统计一次)的集合联系起来,其中有 33,721(?) 个词。上述语句包含一个读取、解码和分割的命令链,每个命令都在一个中间计算实体上操作:我们从打开的 URL 中读取数据,然后将数据解码成文本,最后将文本分割成单词。所有这些词都被放在一个集合(Set,Python 中的一种数据类型)中。
|
||||
|
||||
<strong>对象</strong>
|
||||
**对象**
|
||||
|
||||
前文中提到的 Set,不仅仅是数据类型,也是一个对象。对象用一种能同时处理两者复杂性的方式,把数据和操作该数据的逻辑无缝衔接在一起。
|
||||
|
||||
@@ -91,7 +91,7 @@ words = set(shakespeare.read().decode().split())
|
||||
|
||||
这是一个复合表达式,其值是所有长度为 6 的、本身和反向拼写都在原集合中的词组成的集合。其中的 `w[::-1]` 是一种隐式表达,它枚举了 `w` 中的所有字母,但因为 `step = -1` 规定了步长是反方向的。
|
||||
|
||||
<strong>解释器</strong>
|
||||
**解释器**
|
||||
|
||||
计算复合表达式需要一个精确的程序,以可预测的方式解释代码。一个能实现程序和计算符合表达式的程序被称为解释器;没错,其实解释器是程序(可能再写一篇文章来讲讲解释器和编译器的区别?)
|
||||
|
||||
@@ -109,9 +109,9 @@ words = set(shakespeare.read().decode().split())
|
||||
|
||||
每种强大的语言都有三种这样的机制:
|
||||
|
||||
- <strong>原始的表达式和语句</strong>,代表了该语言提供的最简单的构建模块。
|
||||
- <strong>组合的方式</strong>,由较简单的元素建立成复合元素。
|
||||
- <strong>抽象的手段</strong>,通过它,复合元素可以作为单位被命名和操作。
|
||||
- **原始的表达式和语句**,代表了该语言提供的最简单的构建模块。
|
||||
- **组合的方式**,由较简单的元素建立成复合元素。
|
||||
- **抽象的手段**,通过它,复合元素可以作为单位被命名和操作。
|
||||
|
||||
在编程中,我们处理两种元素:函数和数据。(很快就会发现,它们其实并不那么明显)。不那么正式地说,数据是我们想要操作的东西,而函数描述了操作数据的规则。因此,任何强大的编程语言都应该能够描述原始数据和原始函数,以及有一些方法来组合和抽象函数和数据。
|
||||
|
||||
@@ -133,20 +133,20 @@ words = set(shakespeare.read().decode().split())
|
||||
0.9921875
|
||||
```
|
||||
|
||||
这些数学表达式使用<em>中缀</em>符号,其中<em>运算符</em>(例如,+,-,*,或/)出现在<em>操作数</em>(数字)之间。Python 包括许多形成复合表达式的方法。我们不会试图立即列举它们,而是会随着我们的学习引入新的表达形式,以及它们所支持的语言特性。
|
||||
这些数学表达式使用*中缀*符号,其中*运算符*(例如,+,-,*,或/)出现在*操作数*(数字)之间。Python 包括许多形成复合表达式的方法。我们不会试图立即列举它们,而是会随着我们的学习引入新的表达形式,以及它们所支持的语言特性。
|
||||
|
||||
最重要的一种复合表达式是<em>调用表达式</em>,它将一个函数应用于一些参数。回顾一下代数,函数的数学概念是一个从一些自变量到因变量的映射。例如,一个求最大值的函数将其的多个输入映射到当中最大值的一个单一的输出。Python 表达函数应用的方式与传统数学中相同。
|
||||
最重要的一种复合表达式是*调用表达式*,它将一个函数应用于一些参数。回顾一下代数,函数的数学概念是一个从一些自变量到因变量的映射。例如,一个求最大值的函数将其的多个输入映射到当中最大值的一个单一的输出。Python 表达函数应用的方式与传统数学中相同。
|
||||
|
||||
```python
|
||||
>>> max(7.5, 9.5)
|
||||
9.5
|
||||
```
|
||||
|
||||
这个调用表达式有子表达式:<em>操作符</em>是括号前的表达式,它包含了一个用逗号分隔的<em>操作数</em>列表。
|
||||
这个调用表达式有子表达式:*操作符*是括号前的表达式,它包含了一个用逗号分隔的*操作数*列表。
|
||||
|
||||

|
||||
|
||||
运算符指定了一个<em>函数</em>。当这个调用表达式被评估时,我们说对<em>参数</em>`7.5` 和 `9.5`<em>调用</em>函数 `max`,并<em>返回</em>一个 9.5 的<em>返回值</em>。
|
||||
运算符指定了一个*函数*。当这个调用表达式被评估时,我们说对*参数*`7.5` 和 `9.5`*调用*函数 `max`,并*返回*一个 9.5 的*返回值*。
|
||||
|
||||
调用表达式中参数的顺序很重要。例如,函数 `pow` 计算第一个参数的第二个参数次方。
|
||||
|
||||
@@ -166,7 +166,7 @@ words = set(shakespeare.read().decode().split())
|
||||
|
||||
不会产生歧义,因为函数名总是优先于其参数。
|
||||
|
||||
此外,函数符号以一种直接的方式延伸到<em>嵌套表达式</em>,其中的元素本身就是复合表达式。在嵌套的调用表达式中,与复合的中缀表达式不同,嵌套的结构在括号中是完全明确的。
|
||||
此外,函数符号以一种直接的方式延伸到*嵌套表达式*,其中的元素本身就是复合表达式。在嵌套的调用表达式中,与复合的中缀表达式不同,嵌套的结构在括号中是完全明确的。
|
||||
|
||||
```python
|
||||
>>> max(min(1, -2), min(pow(3, 5), -4))
|
||||
@@ -205,7 +205,7 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
|
||||
### 变量名和环境
|
||||
|
||||
编程语言的一个关键方面是它提供了使用变量名来指代计算对象的手段。如果一个值被赋予了一个变量名,我们就说这个变量名与这个值<em>绑定</em>了。
|
||||
编程语言的一个关键方面是它提供了使用变量名来指代计算对象的手段。如果一个值被赋予了一个变量名,我们就说这个变量名与这个值*绑定*了。
|
||||
|
||||
在 Python 中,我们可以使用赋值语句建立新的绑定,其中包含左边的变量名 `=` 右边的值。
|
||||
|
||||
@@ -225,9 +225,9 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
1.0002380197528042
|
||||
```
|
||||
|
||||
`=` 符号在 Python(以及许多其他语言)中被称为<em>赋值</em>操作符。赋值是我们最简单的抽象手段,因为它允许我们使用简单的名称来指代复合操作的结果。用这种方式,复杂的程序就是通过一步一步地建立复杂度越来越高的计算对象来构建的。
|
||||
`=` 符号在 Python(以及许多其他语言)中被称为*赋值*操作符。赋值是我们最简单的抽象手段,因为它允许我们使用简单的名称来指代复合操作的结果。用这种方式,复杂的程序就是通过一步一步地建立复杂度越来越高的计算对象来构建的。
|
||||
|
||||
将变量名与值绑定,然后通过变量名检索这些值意味着解释器必须保持某种内存,以跟踪变量名、值和绑定。这样的内存空间被称为<em>环境</em>。
|
||||
将变量名与值绑定,然后通过变量名检索这些值意味着解释器必须保持某种内存,以跟踪变量名、值和绑定。这样的内存空间被称为*环境*。
|
||||
|
||||
变量名也可以被绑定到函数上。例如,变量名 `max` 与我们使用的求最大值的函数绑定。与数字不同的是,函数在呈现为文本时很棘手,所以当被要求描述一个函数时,Python 会打印一个识别描述。
|
||||
|
||||
@@ -256,7 +256,7 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
2
|
||||
```
|
||||
|
||||
在 Python 中,名称通常被称为<em>变量名</em>或<em>变量</em>,因为它们在执行程序的过程中可能被绑定到不同的值。当一个名称通过赋值被绑定到一个新的值时,它就不再被绑定到任何以前的值。人们甚至可以将内置名称与新值绑定。
|
||||
在 Python 中,名称通常被称为*变量名*或*变量*,因为它们在执行程序的过程中可能被绑定到不同的值。当一个名称通过赋值被绑定到一个新的值时,它就不再被绑定到任何以前的值。人们甚至可以将内置名称与新值绑定。
|
||||
|
||||
```python
|
||||
>>> max = 5
|
||||
@@ -315,7 +315,7 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
1. 计算运算符和操作数的子表达式,然后
|
||||
2. 将作为运算符子表达式的值的函数应用于作为运算符子表达式的值的参数。
|
||||
|
||||
即使这是个简单的程序也说明了关于一般过程的一些重要观点。第一步决定了为了完成一个调用表达式的计算过程,我们必须首先计算其他表达式。因此,计算过程在本质上是<em>递归的</em>;也就是说,作为其步骤之一,它也包括调用规则本身。
|
||||
即使这是个简单的程序也说明了关于一般过程的一些重要观点。第一步决定了为了完成一个调用表达式的计算过程,我们必须首先计算其他表达式。因此,计算过程在本质上是*递归的*;也就是说,作为其步骤之一,它也包括调用规则本身。
|
||||
|
||||
例如,计算
|
||||
|
||||
@@ -328,7 +328,7 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
|
||||

|
||||
|
||||
这张插图被称为<em>表达式树</em>。在计算机科学中,树(Tree,一种数据结构,我们将在后续的章节中进行讨论)通常是自上而下生长的。树中每一点的对象被称为节点;在这张插图的情况下,节点是与值配对的表达式。
|
||||
这张插图被称为*表达式树*。在计算机科学中,树(Tree,一种数据结构,我们将在后续的章节中进行讨论)通常是自上而下生长的。树中每一点的对象被称为节点;在这张插图的情况下,节点是与值配对的表达式。
|
||||
|
||||
计算它的根,即顶部的完整表达式,需要首先计算作为其子表达式的分支。叶表达式(即没有分支的节点)代表函数或数字。内部节点有两个部分:我们的计算规则所适用的调用表达式,以及该表达式的结果。从这棵树的计算来看,我们可以想象操作数的值是向上渗滤的,从末端节点开始,然后在越来越高的层级上进行组合。
|
||||
|
||||
@@ -357,7 +357,7 @@ Python 定义了大量的函数,包括上一节中提到的运算符函数,
|
||||
|
||||
这个语句不返回一个值,也不在某些参数上调用一个函数,因为赋值的目的是将一个变量名绑定到一个值上。
|
||||
|
||||
一般来说,赋值语句不是被计算而是<em>被执行</em>;它们不产生一个值,而是做一些改变。每种类型的表达式或语句都有自己的计算或执行过程。
|
||||
一般来说,赋值语句不是被计算而是*被执行*;它们不产生一个值,而是做一些改变。每种类型的表达式或语句都有自己的计算或执行过程。
|
||||
|
||||
### 纯函数和非纯函数
|
||||
|
||||
|
||||
Reference in New Issue
Block a user