From af9cc76162a4bd5c8561541adc8c18d5c8085eaf Mon Sep 17 00:00:00 2001 From: LeiSure <114684832+FallenYing@users.noreply.github.com> Date: Thu, 4 Jul 2024 20:35:16 +0800 Subject: [PATCH] delete 3.6.5 (#249) * docs: update 3.5 * fix: * delete 3.6.5 --- .vitepress/sidebar.js | 8 - .../3.6.5.1CS61A Sec1.md | 469 ------------------ .../3.6.5CS61A食用指南.md | 141 ------ 3 files changed, 618 deletions(-) delete mode 100644 3.编程思维体系构建/3.6.5.1CS61A Sec1.md delete mode 100644 3.编程思维体系构建/3.6.5CS61A食用指南.md diff --git a/.vitepress/sidebar.js b/.vitepress/sidebar.js index 144fc2c..f776719 100644 --- a/.vitepress/sidebar.js +++ b/.vitepress/sidebar.js @@ -267,14 +267,6 @@ export function chapter3() { { text: '3.6.4.6结语', link: '/3.编程思维体系构建/3.6.4.6结语' }, ] }, - { - text: '3.6.5 CS61A 食用指南', - collapsed: true, - items: [ - { text: '3.6.5 CS61A 食用指南', link: '/3.编程思维体系构建/3.6.5CS61A食用指南' }, - { text: '3.6.5.1 CS61A Sec1', link: '/3.编程思维体系构建/3.6.5.1CS61A Sec1' }, - ] - } ] }, { text: '3.X 聊聊设计模式和程序设计', link: '/3.编程思维体系构建/3.X 聊聊设计模式和程序设计' }, diff --git a/3.编程思维体系构建/3.6.5.1CS61A Sec1.md b/3.编程思维体系构建/3.6.5.1CS61A Sec1.md deleted file mode 100644 index da5572f..0000000 --- a/3.编程思维体系构建/3.6.5.1CS61A Sec1.md +++ /dev/null @@ -1,469 +0,0 @@ -# CS61A Sec1 - -**观前须知:** - -本章节内容基于 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)下所许可的。 - -计算机科学的高生产力之所以可能,是因为该学科是建立在一套优雅而强大的基本思想之上。所有的程序都从信息的表示开始,然后寻找一种逻辑来处理这些信息,并设计抽象概念来解释和控制这种逻辑。有了这些认识后,我们就需要准确的理解计算机是如何解释我们写的程序并进行计算的。 - -> A language isn't something you learn so much as something you join.
—[Arika Okrent](http://arikaokrent.com/) - -为了定义计算过程,我们需要一种编程语言;最好是许多人类和大量的计算机都能理解的语言。所以在 cs61a 中,伯克利主要使用 Python 语言来进行教学。 - -(在之前的 cs61a 课程中,Berkeley 大学主要使用 Scheme 来进行教学,(可能会写一篇文章来说说 Python 和 Scheme 语言和编程上的区别?) 不过在现在的课程中还是有关于 Scheme 的内容,所以并不用太过伤心?🙄) - -## 学习目标 - -在这一部分我们要学习的内容主要是函数(Functions) - -### 一个简单的例子 - -::: warning A Midsummer-Night's Dream: -And, as imagination bodies forth - -The forms of things to unknown, and the poet's pen - -Turns them to shapes, and gives to airy nothing - -A local habitation and a name. - -—William Shakespeare -::: - -为了给 Python 一个适当的介绍,我们将从一个使用几种语言特征的例子开始。 - -Python 内置了对广泛的常见编程的支持,如操作文本、显示图形和通过互联网进行通信。 - -```python -from urllib.request import urlopen -``` - -这个 Python 代码是一个导入语句,加载了在互联网上访问数据的功能。实际上,它提供了一个叫做 urlopen 的函数,它可以在一个[统一资源定位符(URL)](https://developer.mozilla.org/zh-CN/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL)上访问内容,可以通过它来访问互联网上的数据。 - -**语句和表达式** - -Python 代码由语句和表达式组成。大体上,计算机程序由以下指令组成 - -1. 计算一些值 -2. 进行一些操作 - -语句通常描述行动;当 Python 解释器执行一个语句时,它执行相应的动作。另一方面,表达式通常描述的是计算;当 Python 评估一个表达式时,它计算该表达式的值。在这篇文章下,介绍了几种类型的声明和表达方式。 - -**赋值语句** - -```python -shakespeare = urlopen('http://www.composingprograms.com/shakespeare.txt') -``` - -注意:在伯克利大学的教材中,上述代码中的 url 并没有添加"www.",导致现在(至少在写这篇文章的时候)无法打开原文中的 url(可能还会写一篇文章来讲解"www."?) - -将变量名 `shakespeare` 用 `=` 和后面的表达式的值联系起来。该表达式将 `urlopen` 函数应用于一个 URL,该 URL 包含威廉 - 莎士比亚 37 部戏剧的完整文本,全部保存在一个文本文件中。 - -**函数** - -函数封装了操作数据的逻辑。 - -这句话告诉我们,可以从两个角度来看函数: - -- 在调用函数的时候,我们关注的是要处理的数据 -- 在定义函数的时候,我们关注的是如何处理数据 - -```python -shakespeare = urlopen('http://www.composingprograms.com/shakespeare.txt') -``` - -`urlopen` 是一个函数。一个网络地址是一种数据,而莎士比亚戏剧的文本是另一种数据。从网络地址到文本的过程可能很复杂,但我们可以只用一个简单的表达式来应用这个过程,因为这个复杂性被藏在一个函数中。 - -你可能不了解 `urlopen` 这个函数背后的逻辑,但这不影响你去调用这个函数,这就是函数封装的好处之一。 - -**因此,函数是本章节关注的重点。** - -我们来看另一个赋值语句: - -```python -words = set(shakespeare.read().decode().split()) -``` - -这个语句将名字词与莎士比亚戏剧中出现的所有出现过的词(重复出现的词只统计一次)的集合联系起来,其中有 33,721(?) 个词。上述语句包含一个读取、解码和分割的命令链,每个命令都在一个中间计算实体上操作:我们从打开的 URL 中读取数据,然后将数据解码成文本,最后将文本分割成单词。所有这些词都被放在一个集合(Set,Python 中的一种数据类型)中。 - -**对象** - -前文中提到的 Set,不仅仅是数据类型,也是一个对象。对象用一种能同时处理两者复杂性的方式,把数据和操作该数据的逻辑无缝衔接在一起。 - -对象会是我们后面章节所要讨论的内容。 - -现在让我们来看这个例子中的最后一个语句: - -```python ->>> {w for w in words if len(w) == 6 and w[::-1] in words} -{'redder', 'drawer', 'reward', 'diaper', 'repaid'} -``` - -第一行的">>>"表示输入,第二行则是交互式会话的输出 - -这是一个复合表达式,其值是所有长度为 6 的、本身和反向拼写都在原集合中的词组成的集合。其中的 `w[::-1]` 是一种隐式表达,它枚举了 `w` 中的所有字母,但因为 `step = -1` 规定了步长是反方向的。 - -**解释器** - -计算复合表达式需要一个精确的程序,以可预测的方式解释代码。一个能实现程序和计算符合表达式的程序被称为解释器;没错,其实解释器是程序(可能再写一篇文章来讲讲解释器和编译器的区别?) - -与其他计算机程序相比,编程语言的解释器在通用性方面是独一无二的。Python 的设计没有考虑到莎士比亚,然而,它的不可思议的灵活性使我们能够只用几个语句和表达式来处理大量的文本。 - -最后,我们会发现所有这些核心概念都是密切相关的:函数是对象,对象是函数,而解释器是两者的实例。然而,要掌握编程的艺术,关键是要清楚地理解每个概念及其在组织代码中的作用。 - -解释器的设计和实现也是我们之后的主要议题。 - -### 编程要素 - -编程语言不仅仅是指示计算机执行任务的一种手段,同时也是一个框架,我们在这个框架内组织我们关于计算过程的想法。程序的作用是在编程社区的成员之间交流这些想法,所以,编写的程序必须让人们容易阅读,而且只是顺便让机器执行。 - -当我们描述一种语言时,我们应该特别注意该语言为结合简单的想法以形成更复杂的想法所提供的手段。 - -每种强大的语言都有三种这样的机制: - -- **原始的表达式和语句**,代表了该语言提供的最简单的构建模块。 -- **组合的方式**,由较简单的元素建立成复合元素。 -- **抽象的手段**,通过它,复合元素可以作为单位被命名和操作。 - -在编程中,我们处理两种元素:函数和数据。(很快就会发现,它们其实并不那么明显)。不那么正式地说,数据是我们想要操作的东西,而函数描述了操作数据的规则。因此,任何强大的编程语言都应该能够描述原始数据和原始函数,以及有一些方法来组合和抽象函数和数据。 - -在上一小节中对 Python 解释器进行了实验后,我们现在重新开始,有条不紊地逐个开发 Python 语言元素。如果例子看起来很简单,那就耐心一点,因为更多令人兴奋的点很快就会出现。 - -我们从原始表达式开始。一种原始表达式是数字。更确切地说,你输入的表达式由代表十进制的数字组成。 - -```python ->>> 42 -42 -``` - -代表数字的表达式可以与数学运算符相结合,形成一个复合表达式,解释器将对其进行计算。 - -```python ->>> -1 - -1 -0 ->>> 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/64 + 1/128 -0.9921875 -``` - -这些数学表达式使用*中缀*符号,其中*运算符*(例如,+,-,\*,或/)出现在*操作数*(数字)之间。Python 包括许多形成复合表达式的方法。我们不会试图立即列举它们,而是会随着我们的学习引入新的表达形式,以及它们所支持的语言特性。 - -最重要的一种复合表达式是*调用表达式*,它将一个函数应用于一些参数。回顾一下代数,函数的数学概念是一个从一些自变量到因变量的映射。例如,一个求最大值的函数将其的多个输入映射到当中最大值的一个单一的输出。Python 表达函数应用的方式与传统数学中相同。 - -```python ->>> max(7.5, 9.5) -9.5 -``` - -这个调用表达式有子表达式:*操作符*是括号前的表达式,它包含了一个用逗号分隔的*操作数*列表。 - -![](https://cdn.xyxsw.site/call_expression.png) - -运算符指定了一个*函数*。当这个调用表达式被评估时,我们说对*参数*`7.5` 和 `9.5`*调用*函数 `max`,并*返回*一个 9.5 的*返回值*。 - -调用表达式中参数的顺序很重要。例如,函数 `pow` 计算第一个参数的第二个参数次方。 - -```python ->>> pow(100, 2) -10000 ->>> pow(2, 100) -1267650600228229401496703205376 -``` - -与中缀表示法的数学约定相比,函数表示法有三个主要优点。首先,函数可以接受任意数量的参数: - -```python ->>> max(1, -2, 3, -4) -3 -``` - -不会产生歧义,因为函数名总是优先于其参数。 - -此外,函数符号以一种直接的方式延伸到*嵌套表达式*,其中的元素本身就是复合表达式。在嵌套的调用表达式中,与复合的中缀表达式不同,嵌套的结构在括号中是完全明确的。 - -```python ->>> max(min(1, -2), min(pow(3, 5), -4)) --2 -``` - -对于这种嵌套的深度以及 Python 解释器可以计算的表达式的整体复杂性,(原则上)没有限制。然而,人类很快就会被多级嵌套所迷惑。作为一个程序员,你的一个重要作用是构造表达式,使它们仍然可以由你自己、你的编程伙伴和其他将来可能阅读你的表达式的人来解释。 - -同时,数学符号有各种各样的形式:乘法出现在术语之间,指数显示为上标,除法显示为斜杠,平方根显示为有斜边的屋顶。其中一些符号是很难打出来的!然而,所有这些复杂性都可以通过调用表达式的符号来统一。虽然 Python 支持使用中缀表达式的常见数学运算符(如 `+` 和 `-`),但任何运算符都可以表示为一个有名称的函数。 - -### 导入库函数 - -Python 定义了大量的函数,包括上一节中提到的运算符函数,但默认不提供它们的所有名称。作为替代,它将函数和其他量组织到模块中,这些模块共同构成了 Python 库。为了使用这些元素,人们将它们导入。例如,数学模块提供了各种熟悉的数学相关的函数。 - -```python ->>> from math import sqrt ->>> sqrt(256) -16.0 -``` - -而运算符模块提供了对应于中缀表达式的函数的访问: - -```python ->>> from operator import add, sub, mul ->>> add(14, 28) -42 ->>> sub(100, mul(7, add(8, 4))) -16 -``` - -一个导入语句指定了一个模块的名称(例如,`operator` 或 `math`),然后列出要导入的该模块的命名属性(例如,`sqrt`)。一旦一个函数被导入,它可以被多次调用。 - -使用这些运算符函数(如 `add`)和运算符符号本身(如 `+`)之间没有区别。传统上,大多数程序员使用符号和中缀表达式来表达简单的算术。 - -[Python 3 库文档](https://docs.python.org/3/library/index.html)列出了每个模块所定义的功能,如[数学模块](https://docs.python.org/3/library/math.html)。然而,这个文档是为那些对整个语言很了解的开发者编写的。现在,你可能会发现,对一个函数进行实验比阅读文档能告诉你更多关于它的行为。随着你对 Python 语言和词汇的熟悉,这个文档将成为有价值的参考来源。 - -### 变量名和环境 - -编程语言的一个关键方面是它提供了使用变量名来指代计算对象的手段。如果一个值被赋予了一个变量名,我们就说这个变量名与这个值*绑定*了。 - -在 Python 中,我们可以使用赋值语句建立新的绑定,其中包含左边的变量名 `=` 右边的值。 - -```python ->>> radius = 10 ->>> radius -10 ->>> 2 * radius -20 -``` - -变量名也是可以通过导入语句来绑定的。 - -```python ->>> from math import pi ->>> pi * 71 / 223 -1.0002380197528042 -``` - -`=` 符号在 Python(以及许多其他语言)中被称为*赋值*操作符。赋值是我们最简单的抽象手段,因为它允许我们使用简单的名称来指代复合操作的结果。用这种方式,复杂的程序就是通过一步一步地建立复杂度越来越高的计算对象来构建的。 - -将变量名与值绑定,然后通过变量名检索这些值意味着解释器必须保持某种内存,以跟踪变量名、值和绑定。这样的内存空间被称为*环境*。 - -变量名也可以被绑定到函数上。例如,变量名 `max` 与我们使用的求最大值的函数绑定。与数字不同的是,函数在呈现为文本时很棘手,所以当被要求描述一个函数时,Python 会打印一个识别描述。 - -```python ->>> max - -``` - -我们可以使用赋值语句给现有的函数起别名。 - -函数也可以看作是值。 - -```python ->>> f = max ->>> f - ->>> f(2, 3, 4) -4 -``` - -在同一个环境下的连续的赋值语句可以将一个名字重新绑定到一个新的值。 - -```python ->>> f = 2 ->>> f -2 -``` - -在 Python 中,名称通常被称为*变量名*或*变量*,因为它们在执行程序的过程中可能被绑定到不同的值。当一个名称通过赋值被绑定到一个新的值时,它就不再被绑定到任何以前的值。人们甚至可以将内置名称与新值绑定。 - -```python ->>> max = 5 ->>> max -5 -``` - -在将 `max` 赋值为 5 后,`max` 这个名称不再与函数绑定,因此试图调用 `max(2, 3, 4)` 会造成错误。 - -在执行赋值语句时,Python 在改变对左边变量名的绑定之前,对 `=` 右边的表达式进行计算。因此,人们可以在右侧表达式中引用一个变量名,即使它是要被赋值语句绑定的变量名。 - -```python ->>> x = 2 ->>> x = x + 1 ->>> x -3 -``` - -我们还可以在一个语句中给多个变量名赋值,其中左边的变量名和右边的表达式分别用逗号隔开。 - -```python ->>> area, circumference = pi * radius * radius, 2 * pi * radius ->>> area -314.1592653589793 ->>> circumference -62.83185307179586 -``` - -改变一个变量的值并不影响其他变量。下面,尽管变量名 `area` 被绑定到一个最初以 `radius` 定义的值,但 `area` 的值并没有改变。更新 `area` 的值需要另一个赋值语句。 - -```python ->>> radius = 11 ->>> area -314.1592653589793 ->>> area = pi * radius * radius -380.132711084365 -``` - -通过多重赋值的语句,在左边的任何变量名被绑定到这些值之前,右边的所有表达式都将被计算。由于这个规则,交换绑定在两个变量名上的值可以在一个语句中进行。 - -```python ->>> x, y = 3, 4.5 ->>> y, x = x, y ->>> x -4.5 ->>> y -3 -``` - -### 计算嵌套表达式 - -我们在本小节的目标之一是分离出关于像程序一样思考的问题。从下面这个例子中,我们应该意识到,在计算嵌套调用表达式时,解释器本身是在遵循某种步骤。 - -为了计算一个调用表达式,Python 将做按以下规则来工作: - -1. 计算运算符和操作数的子表达式,然后 -2. 将作为运算符子表达式的值的函数应用于作为运算符子表达式的值的参数。 - -即使这是个简单的程序也说明了关于一般过程的一些重要观点。第一步决定了为了完成一个调用表达式的计算过程,我们必须首先计算其他表达式。因此,计算过程在本质上是*递归的*;也就是说,作为其步骤之一,它也包括调用规则本身。 - -例如,计算 - -```python ->>> sub(pow(2, add(1, 10)), pow(2, 5)) -2016 -``` - -需要这个按照上述过程重复四次。如果我们画出每个被计算的表达式,我们就可以直观地看到这个过程的层次结构。 - -![](https://cdn.xyxsw.site/expression_tree.png) - -这张插图被称为*表达式树*。在计算机科学中,树(Tree,一种数据结构,我们将在后续的章节中进行讨论)通常是自上而下生长的。树中每一点的对象被称为节点;在这张插图的情况下,节点是与值配对的表达式。 - -计算它的根,即顶部的完整表达式,需要首先计算作为其子表达式的分支。叶表达式(即没有分支的节点)代表函数或数字。内部节点有两个部分:我们的计算规则所适用的调用表达式,以及该表达式的结果。从这棵树的计算来看,我们可以想象操作数的值是向上渗滤的,从末端节点开始,然后在越来越高的层级上进行组合。 - -接下来,观察一下,步骤一的重复应用使我们需要计算的不是调用表达式,而是数字(如 `2`)和名称(如 `add`)等原始表达式。 - -我们通过规定以下几点来处理这种情况: - -- 数字计算为它的名称所代表的数量 -- 名称计算为与当前环境中的名称相关的值。 - -请注意环境在决定表达式中符号的含义方面的重要作用。在 Python 中,在没有给定环境或是明确所有名称所指代的内容时,谈论一个表达式的价值是没有意义的,比如 - -```python ->>> add(x, 1) -``` - -而不指定任何关于环境为名称 `x`(甚至是名称 `add`)提供意义的信息。环境提供了计算发生的背景,这对我们理解程序执行起着重要作用。 - -上述的计算过程不足以计算所有的 Python 代码,只计算调用表达式、数字和名称。 - -例如,它不处理赋值语句 - -```python ->>> x = 3 -``` - -这个语句不返回一个值,也不在某些参数上调用一个函数,因为赋值的目的是将一个变量名绑定到一个值上。 - -一般来说,赋值语句不是被计算而是*被执行*;它们不产生一个值,而是做一些改变。每种类型的表达式或语句都有自己的计算或执行过程。 - -### 纯函数和非纯函数 - -在本小节中,我们将区分两种函数 -**纯函数** -函数有一些输入(它们的参数)并返回一些输出(应用它们的结果)。 -例如内置函数 - -```python ->>> abs(-2) -2 -``` - -可以被描述为一台接受输入并产生输出的小型机器。 -![](https://cdn.xyxsw.site/function_abs.png) -函数 `abs` 是*纯函数*。纯函数的特性是,调用它们除了返回一个值之外没有任何影响。此外,当用相同的参数调用两次时,一个纯函数必须总是返回相同的值。 - -**非纯函数** -除了返回一个值之外,应用一个非纯函数会产生副作用,从而使解释器或计算机的状态发生一些变化。一个常见的副作用是,使用`print`函数,在返回值之外产生额外的输出。 - -```python ->>> print(1, 2, 3) -1 2 3 -``` - -虽然`print`和`abs`在这些例子中可能看起来很相似,但它们的工作方式根本不同。打印返回的值总是`None`,这是一个特殊的 Python 值,不代表任何东西。交互式 Python 解释器不会自动打印值`None`。在`print`的情况下,函数本身是打印输出,也是被调用的副作用。 -![](https://cdn.xyxsw.site/function_print.png) - -对`print`函数的嵌套调用突出了纯函数和非纯函数的区别 - -```python ->>> print(print(1), print(2)) -1 -2 -None None -``` - -如果你发现这个输出出乎意料,可以画一个表达式树来弄清楚为什么计算这个表达式会产生这个奇特的输出。 - -请注意!`print`函数的返回值`None`意味着它*不应该*是赋值语句中的表达式。 - -```python ->>> two = print(2) -2 ->>> print(two) -None -``` - -纯函数是被限制的,因为它们不能有副作用或随时间改变行为。施加这些限制会产生巨大的好处。 -首先,纯函数可以更可靠地组成复合调用表达式。我们可以在上面的非纯函数例子中看到,`print`在操作数表达式中使用时并没有返回一个我们期望的结果。另一方面,我们已经看到,像`max`、`pow`和`sqrt`这样的函数可以有效地用于嵌套表达式。 -其次,纯函数往往更容易测试。一个参数列表将总是导致相同的返回值,这可以与预期返回值进行比较。关于测试将在之后的章节详细讨论。 - -在之后的章节中,我们将说明纯函数对于编写并发程序的重要性,其中多个调用表达式可以同时被计算。 -与之对应的,我们也将研究非纯函数并了解他们的用途。 - -出于这些问题的考虑,我们将在下一章节中着重讨论创建和使用纯函数。`print`函数的使用只是为了让我们看到计算的中间结果。 - -### 错误和调试 - -Python 正在等待你的命令。我们鼓励你尝试该语言,即使你可能还不知道它的全部语法和结构。但是,请做好应对错误准备。虽然计算机非常快速和灵活,但它们也非常僵化。计算机的本质在[斯坦福大学的入门课程](http://web.stanford.edu/class/cs101/code-1-introduction.html)中被描述为 - -::: warning The fundamental equation of computers is: -**computer = powerful + stupid** - -Coputers are very powerful, looking at volumes of data very quickly. Computers can perform billions of operations per second, where each operation is pretty simple. - -Computers are also shockingly stupid and fragile. The operations that they can do are extremely rigid, simple, and mechanical. The computer lacks anything like real insight ... it's nothing like the HAL 9000 from the movies. If nothing else, you should not be intimidated by the computer as if it's some sort of brain. It's very mechanical underneath it all. - -Programming is about a person using their real insight to build something useful, constructed out of these teeny, simple little operations that the computer can do. - -—Francisco Cai and Nick Parlante, Stanford CS101 -::: - -当你尝试使用 Python 解释器时,计算机的僵化将立即变得明显:即使是最小的拼写和格式更改也会导致意外的输出和错误。 - -学习解释错误和诊断意外错误的原因称为调试。调试的一些指导原则是: - -1. **逐步测试**: -每个编写良好的程序都由可以单独测试的小型模块化组件组成。尽快尝试测试你编写的所有内容,以便及早发现问题并获得对组件的信心。 -2. **隔离错误**: -语句输出中的错误通常可归因于特定的模块化组件。尝试诊断问题时,请在尝试更正错误之前将错误跟踪到最小的代码片段。 -3. **检查假设**: -解释器会完全执行你的指示 —— 不会多也不会少。当某些代码的行为与程序员认为(或假设)的结果不匹配时,那么输出就是出乎意料的。重新检查你的假设,然后将调试工作集中在验证你的假设是否确实成立上。 -4. **咨询他人**: -你并不孤单!如果你不理解错误消息,请咨询朋友、教师或搜索引擎。如果你已隔离出错误,但无法弄清楚如何纠正它,请让其他人查看。在小组解决问题的过程中,许多有价值的编程知识会被分享。 - -逐步测试、模块化设计、精确的假设和团队合作是贯穿本文的主题。希望它们也能贯穿你的计算机科学生涯。 - -## 课后作业 - -一个好的课程怎么能少得了精心准备的课后作业呢?🤗 - -如果被题目卡住了,那就再去看看食用指南吧!😋 - -::: tip 📥 -本小节课后作业下载 -::: diff --git a/3.编程思维体系构建/3.6.5CS61A食用指南.md b/3.编程思维体系构建/3.6.5CS61A食用指南.md deleted file mode 100644 index a54665d..0000000 --- a/3.编程思维体系构建/3.6.5CS61A食用指南.md +++ /dev/null @@ -1,141 +0,0 @@ -# CS61A 食用指南 - -## 关于 CS61A - -这是 CS 61A Fall 2022 的网站: - -[https://inst.eecs.berkeley.edu/~cs61a/fa22/](https://inst.eecs.berkeley.edu/~cs61a/fa22/) - -在这个目录下的文章上传的 pdf 基本都是英文的,还请做好准备。 - -在每个 disc、lab、hw 和 proj 下,都会有相对应的.zip 文件,文件里装的是在学习过程中所需要的代码。 - -在文章的最后会附上 sol。 - -当然,在没有头绪的时候,你可以选择参考 sol,也可以重新学习视频和教科书,也可以改变做题的顺序。 - -ps:哪怕是 cs61a 这样优秀的课程,给出的解决方案里也会有不是那么正确的代码(它并不能处理所有的情况) - -pps:如果你找到了 sol 里不是那么正确的代码,请联系我们,我们将新建一个文档来记录 sol 中这些“错误”的代码 - -ppps:当然存在“错误”的代码的概率很小,你发现它们的概率就更小了 - -pppps:不只是在 sol 文件中,youtube 上的视频中的代码也可能会出现一些小问题 - -## 为什么要学 CS61A? - -简单来说,学校的编程课只能教会你一些最基本的语法和代码逻辑,从学校的课程中,你很难学到一些实用的编程思想 (甚至一些老师自己也讲不明白)。一部分原因当然是老师上课完全没有想过如何渗透这些编程思想;还有一部分原因我认为是课后作业是在过于随意了,PTA 上的课后作业只是用来检测你是否掌握了一些最基础的语法,这样的题目是很难培养学生的编程思想的。 - -## 从 CS61A 中能学到什么? - -分语言来看,cs61a 讲了这三种语言: - -1. Python -2. Scheme -3. SQL - -分章节来看,cs61a 主要教了以下这些内容: - -1. 用函数构建抽象关系 - - 1. 函数与函数设计 - 2. 控制 - 3. 高级函数 - 4. 递归函数 -2. 用数据构建抽象关系 - - 1. 数据抽象 - 2. 可变数据 - 3. 面向对象编程 -3. 解释计算机程序 - - 1. 函数式编程 - 2. 异常 - 3. 解释器的开发 -4. 数据处理 - - 1. 声明式编程 - -## CS61A 好在哪里? - -~~暂且不考虑由于是伯克利大学的课程所以视频资料和教科书全是英文~~ - -每一节课程都有完备的视频资料和相对应的教科书,还有精心设计的 lab、hw、disc、proj - -所有题目都有完善的说明、例子、半自动的测试和批改,哪怕英语不是很好的同学也能理解到题目所要表达的意思 - -课程的设计目的是引导学生像计算机那样思考,在课程网站上有相当多的交互式页面来帮助你学习(不过因为我们没有伯克利大学的账号无法使用 🤪) - -课程中还推荐了一个学习 python 很好的网站,可以用来绘制环境图:[Python Tutor](http://tutor.cs61a.org/) - -~~(不像某些学校只会把学生丢进水池里,没淹死的都是学会游泳的好学生)~~ - -John Denero 教授的网课也是非常的有趣,如果你的英语够好,还能发现藏在视频里的一些小彩蛋 🤤 - -## 如何学习 CS61A? - -cs61a 绝对是一个挑战,但是我们都希望你学习并且成功,所以这里有一些可能对你的旅程有所帮助的小贴士: - -- 在 61A 中成功的方法有很多 ーー 我们发现下面的建议适用于几乎所有的学生,但是对不同的人最有效的方法是不同的,我们建议探索不同的学习和工作策略。~~如果你想和助教谈谈你的方法,我们有专门的~~~~咨询办公时间~~~~做这些事情!~~ -- 问问题 - - - 如果你遇到一些你不知道或不确定的概念或问题,_那就来问吧_~~。我们是来帮助你们学习的,如果你们提出一个问题,我们会告诉你们在哪些方面我们可以帮助你们理解这些材料。~~提出问题的过程本身也有助于你自己弄清楚你特别想问什么,从而找出你认为你可以学到更多的概念。 -- 小组学习 - - - 再次强调,这门课对于大多数学生来说都不是一门简单的课程,你可能会感到不知所措。给你的小伙伴们发送一个信息,并与班上的其他同学取得联系; 一起完成作业或一起学习准备考试,只要你不违反课程大纲中规定的诚实学习的[课程政策](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/about/#academic-misconduct)。 -- 当遇到问题时,试着组织语言来解释你遇到困难的地方。 - - - 这并不需要一个找到懂得如何解决问题的人 (或者甚至是一个人——这种做法通常被称为**橡皮鸭**,因为你可以把一只橡皮鸭当作你的练习对象) ,因为主要目标是让你弄清楚你自己的想法,弄清楚你的理解和代码到底在哪里卡住了。这样你可以知道应该专注于哪一部分,以便更好地理解。 -- 做所有的 hw(或者至少认真地尝试)。我们没有给出很多 hw 问题,但那些我们给你的可能会发现是具有挑战性、耗时且有回报的。 -- 做所有的 lab。其中大部分的设计更多的是作为一个课程材料的介绍,并可能需要半个小时左右的时间。这是一个熟悉新的知识点的好时机。 - -因为伯克利大学有着非常好的软硬件设施,所以在他们的课程体系中有助教和专门的论坛来辅助学习。杭电实在是没有这样的资源 🥲,所以在遇到问题的时候请先尝试独立解决,然后再和小伙伴们一起讨论,如果遇到实在解决不了的难题就来参考前人的 [GitHub](https://github.com/E1PsyCongroo/CS61A-FA22) 吧 - -## 如何使用 ok 进行代码测试? - -在 61a 中,我们使用一个名为 ok 的程序对 lab,hw 和 proj 进行自动评分。在你下载的每一份代码文件中,都应该找到 ok 程序。 - -确保在终端打开的路径下,包含 ok 和要测试的代码。 - -要使用 Ok 来运行指定函数的 doctests,请运行以下命令 - -```bash -python3 ok -q #会和你要补充的代码一起给出 -``` - -默认情况下,只有没有通过的测试才会出现。你可以使用-v 选项来显示所有的测试,包括你已经通过的测试 - -```bash -python3 ok -v -``` - -有时我们会看到类似这样的 ok 指令 - -```bash -python3 ok -q control -u -``` - -在终端中输入后,需要按照要求回答问题,有些时候会做为某些函数测试的前置条件 - -一般情况下,执行上述 ok 指令后,都会在终端里提示输入 Berkeley 账号进行提交,这时候输入 `Ctrl+C` 退出即可;不过我们可以在代码后面加上 `--local` 进行本地测试;所有的测试都可以本地完成,不需要联网 - -![](https://cdn.xyxsw.site/ok01.jpg) - -关于使用 Ok 命令的更多信息,请在[此处](https://inst.eecs.berkeley.edu/~cs61a/fa22/articles/using-ok/)了解更多 - -## 在学习过程中,你可以能会遇到的问题和解决方法 - -1. 在 CS61A 的学习过程中,你可能会找不到 61A 的每一个 lab、hw、disc、proj 的答案,这是因为 61A 是不断更新并进行授课的,所以每过一个季度 61A 是会进行换季的,所以为了避免这个问题,请尽早将 61A 主页的每一个答案保存下来。如果你已经遇到了这种问题,那么向已经学习了这门课的学长学姐求助是个不错的选择。 -2. 如果出现以下情况,这说明你的并没有在测试对象的目录进行测试,最简单解决办法就是在你对应位置的目录进行鼠标右键点击“在终端中打开”进行输入测试。 -![](https://cdn.xyxsw.site/ok02.png) - -3. 如果输入了命令后回车没有任何反应,请试试将测试代码的 python3 变为 python 或者 py 进行操作,如果还没有解决请仔细阅读 61A hw 部分的 Using ok,链接一般位于 HW 01 的开头。 -4. 如果在解决问题的过程中遇到了问题,那就多读几遍题目吧,题干中或许会给出 `Hint`,这可能很有用 - -这是 cs61a 的官网[https://cs61a.org/](https://cs61a.org/) - -如果你觉得全英教学对你来说比较困难,可以参考[2.5 以理工科的方式阅读英语](../2.高效学习/2.5以理工科的方式阅读英语.md) - -也可以看看我们本地化之后的 cs61a 课程,我们尽可能准确和符合中文阅读习惯地翻译了 textbook,但我们保留了作业中的英语(绝对不是因为偷懒),来锻炼同学们的英语能力 - -英文学习的痛苦比不上接触国外优秀课程带来的快乐,请保持初心,砥砺前进,祝愿同学们都能有一个有趣的学习体验 🥰