Merge pull request #28 from Relph1119/master

修改剩余章节的格式及内容
This commit is contained in:
Datairon 2023-06-16 22:18:48 +08:00 committed by GitHub
commit 9d485c0426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 556 additions and 438 deletions

View File

@ -1,14 +1,15 @@
## 零基础学python编程思维课程简介
- 课程是由MIT6.00计算机科学和编程导论和笨方法学python结合编写的为的是帮助零基础的同学更好和更容易学习因为我是在学习不同课程时碰到很多问题原因是基础没打好通过学习这个课程可以清楚了解编程思维、代码规范、防御性编程等为以后的学习打好基础。
- 作为基础的一个课程不涉及算法只是基础的python语法和编程思维
- 课程的目标是让0基础的同学学习后可以掌握python的基础使用以及看懂别人写的代码并运用以便学习更多的课程
- 设计课程的原因学习了许多datawhale的课程感觉上缺乏一个入门的课程所以我找到MIT的基础计算机课程6.00作为基础学习以及在图书馆时找学习资料时看见笨方法学python的书好奇是怎样的笨方法学习于是用笨方法开始学python发现笨方法更简单。
- 基础知识是采用笨方法学习法,其实是指令式学习,不采用复制粘贴的方式,针对每个代码进行复现,进步会很快,我个人觉得是很有效的学习方法,所以在这里是建议大家使用这个方法进行学习!!一起加油
## 开源贡献
邓林权、沈一、覃嘉俊、马子阳、左凯文、肖桐、张国亮
## 课程内容
- 学习周期19天
- 任务安排:
@ -25,4 +26,5 @@
| Task07面向对象的编程3天 | 截止时间 07月05日03:00 |
## 联系我们
如果您对我们的课程有任何的问题请随时联系我439736460@qq.com联系时请备注您的身份与职业学校我会听取您宝贵的意见
  如果您对我们的课程有任何的问题请随时联系我439736460@qq.com联系时请备注您的身份与职业学校我会听取您宝贵的意见

View File

@ -140,7 +140,7 @@ Is it less or equal? False
18 print(f"If I add {my_age}, {my_height}, and {my_weight} I get {total}.")
```
#### 练习4
#### 练习1
  将上述代码尝试改成自己的信息。
@ -172,7 +172,7 @@ Is it less or equal? False
22 print(w + e)
```
#### 运行结果
  上述代码的运行结果:
```
There are 10 types of people.
@ -183,19 +183,19 @@ Isn't that joke so funny?! False
This is the left side of...a string with a right side.
```
#### 练习5
#### 练习1
  复习一遍这个程序,并在每一行上面写上注释来解释它。
#### 练习6
#### 练习2
  找到所有把字符串放在字符串里面的地方,一共有 4 处。
#### 练习7
#### 练习3
  你确定有 4 处吗?你怎么知道?也许我爱撒谎呢。
#### 练习8
#### 练习4
  解释一下为什么把 w 和 e 两个字符串用 + 连起来能够弄成一个更长的字符串。
@ -239,7 +239,7 @@ runoob
['runoob', 786, 2.23, 'john', 70.2, 123, 'john']
```
### 练习9
### 练习1
  搜索列表的相关知识,看看还有什么操作?

View File

@ -1,10 +1,10 @@

## 5字典
现在你要学习 Python 中的另一种数据结构——字典Dictionary。字典也叫 dict是一种和列表类似的数据存储方式。但是不同于列表只能用数字获取数据字典可以用任何东西来获取。你可以把字典当成是一个存储和组织数据的数据库。
## 2.5 字典
  现在你要学习 Python 中的另一种数据结构——字典Dictionary。字典也叫 dict是一种和列表类似的数据存储方式。但是不同于列表只能用数字获取数据字典可以用任何东西来获取。你可以把字典当成是一个存储和组织数据的数据库。
让我们比较一下列表和字典的作用。你看,列表可以让你做这些事情:
  让我们比较一下列表和字典的作用。你看,列表可以让你做这些事情:
```python
```shell
>>> things = ['a', 'b', 'c', 'd']
>>> print(things[1])
b
@ -14,11 +14,12 @@ z
>>> things
['a', 'z', 'c', 'd']
```
你可以用数字来索引列表,找到列表里面有些什么。到现在你应该能够理解这一点。但是你还要确保自己明白,你只能用数字来取出列表中的元素。
相比之下,字典能让你用几乎所有的东西,而不只是数字。是的,字典能够把一个东西和另一个东西关联起来,不管它们是什么类型。我们来看看:
  你可以用数字来索引列表,找到列表里面有些什么。到现在你应该能够理解这一点。但是你还要确保自己明白,你只能用数字来取出列表中的元素。
```python
  相比之下,字典能让你用几乎所有的东西,而不只是数字。是的,字典能够把一个东西和另一个东西关联起来,不管它们是什么类型。我们来看看:
```shell
>>> stuff = {'name': 'Zed', 'age': 39, 'height': 6 * 12 + 2}
>>> print(stuff['name'])
Zed
@ -30,9 +31,10 @@ Zed
>>> print(stuff['city'])
SF
```
你会看到我们用了字符串(而不是数字)来从 stuff 字典中取出了我们想要的东西。我们也可以用字符串来给字典添加新的东西。而且,也可以不用字符串,我们可以这样做:
```python
  你会看到我们用了字符串(而不是数字)来从 stuff 字典中取出了我们想要的东西。我们也可以用字符串来给字典添加新的东西。而且,也可以不用字符串,我们可以这样做:
```shell
>>> stuff[1] = "Wow"
>>> stuff[2] = "Neato"
>>> print(stuff[1])
@ -40,22 +42,23 @@ Wow
>>> print(stuff[2])
Neato
```
在这一段代码中我用了数字,所以你看,我在打印字典的时候既可以用数字也可以用字符串来作为键。我可以用任何东西。好吧,大多数东西,不过你现在就假装能够用任何东西吧。
当然,如果一个字典只能放东西那就太蠢了。下面是如何用 'del' 关键词来删除其中的东西:
  在这一段代码中我用了数字,所以你看,我在打印字典的时候既可以用数字也可以用字符串来作为键。我可以用任何东西。好吧,大多数东西,不过你现在就假装能够用任何东西吧。
```python
  当然,如果一个字典只能放东西那就太蠢了。下面是如何用`del`关键词来删除其中的东西:
```shell
>>> del stuff['city']
>>> del stuff[1]
>>> del stuff[2]
>>> stuff
{'name': 'Zed', 'age': 39, 'height': 74}
```
### 一个字典示例
### 2.5.1 一个字典示例
接下来我们要做一个练习,你必须非常仔细,我要求你将这个练习写下来,然后试着弄懂它做了些什么。当你把东西放进字典、随意取出、以及做其他操作的时候记得做一下笔记。
  接下来我们要做一个练习,你必须非常仔细,我要求你将这个练习写下来,然后试着弄懂它做了些什么。当你把东西放进字典、随意取出、以及做其他操作的时候记得做一下笔记。
注意一下这个例子是如何把州名和它们的缩写以及州的缩写和城市映射mapping起来的记住“映射”或者说“关联”associate是字典的核心理念。
  注意一下这个例子是如何把美国的州名和它们的缩写以及州的缩写和城市映射mapping起来的记住“映射”或者说“关联”associate是字典的核心理念。
```python
1 # create a mapping of state to abbreviation
@ -120,11 +123,14 @@ Neato
60 city = cities.get('TX', 'Does Not Exist')
61 print(f"The city for the state 'TX' is: {city}")
```
一个小练习,尝试自己写一个中国省份与省份缩写对应的字典代码
## 6元组
元组是另一个数据类型,类似于 List列表
元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。
### 练习1
  完成一个小练习,尝试自己写一个中国省份与省份缩写对应的字典代码
## 2.6 元组
  元组是另一个数据类型,类似于 List列表。 元组用`()`标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。
```python
tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )
@ -138,7 +144,7 @@ print(tinytuple * 2) # 输出元组两次
print(tuple + tinytuple) # 打印组合的元组
```
以下是元组无效的,因为元组是不允许更新的。而列表是允许更新的:
  以下是元组无效的,因为元组是不允许更新的。而列表是允许更新的:
```python
tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )
@ -147,51 +153,48 @@ tuple[2] = 1000 # 元组中是非法应用
list[2] = 1000 # 列表中是合法应用
```
## 7布尔类型
这个部分相信大家已经很熟悉,在高中和大学数学中经常出现的
在python表述的语法是
## 2.7 布尔类型
• and
• or
• not
• != (不等于)
• == (等于)
• >= (大于等于)
<= (小于等于)
• True
• False
&emsp;&emsp;这个部分相信大家已经很熟悉在高中和大学数学中经常出现的。在python表述的语法是
- and
- or
- not
- `!=` (不等于)
- `==` (等于)
- `>=` (大于等于)
- `<=` (小于等于)
- True
- False
在这个练习中,你将试着在 Python 中运用逻辑表。给以下每一个逻辑问题写下你认为的答案,要么是 True要么是 False。等你把答案写下来再在终端里运行 Python输入每个逻辑问题来确认你的答案是否正确。
&emsp;&emsp;在这个练习中,你将试着在 Python 中运用逻辑表。给以下每一个逻辑问题写下你认为的答案,要么是 True要么是 False。等你把答案写下来再在终端里运行 Python输入每个逻辑问题来确认你的答案是否正确。
```python
1. True and True
2. False and True
3. 1 == 1 and 2 == 1
4. "test" == "test"
5. 1 == 1 or 2 != 1
6. True and 1 == 1
7. False and 0 != 0
8. True or 1 == 1
9. "test" == "testing"
10. 1 != 0 and 2 == 1
11. "test" != "testing"
12. "test" == 1
13. not (True and False)
14. not (1 == 1 and 0 != 1)
15. not (10 == 1 or 1000 == 1000)
16. not (1 != 10 or 3 == 4)
17. not ("testing" == "testing" and "Zed" == "Cool Guy")
18. 1 == 1 and (not ("testing" == 1 or 1 == 0))
19. "chunky" == "bacon" and (not (3 == 4 or 3 == 3))
20. 3 == 3 and (not ("testing" == "testing" or "Python" == "Fun"))
1 True and True
2 False and True
3 1 == 1 and 2 == 1
4 "test" == "test"
5 1 == 1 or 2 != 1
6 True and 1 == 1
7 False and 0 != 0
8 True or 1 == 1
9 "test" == "testing"
10 1 != 0 and 2 == 1
11 "test" != "testing"
12 "test" == 1
13 not (True and False)
14 not (1 == 1 and 0 != 1)
15 not (10 == 1 or 1000 == 1000)
16 not (1 != 10 or 3 == 4)
17 not ("testing" == "testing" and "Zed" == "Cool Guy")
18 1 == 1 and (not ("testing" == 1 or 1 == 0))
19 "chunky" == "bacon" and (not (3 == 4 or 3 == 3))
20 3 == 3 and (not ("testing" == "testing" or "Python" == "Fun"))
```
##### 你将会看到
&emsp;&emsp;在你尝试给出所有答案后,这是你可能会在 Python 运行后看到的运行结果:
在你尝试给出所有答案后,这是你可能会在 Python 运行后看到的会话结果:
```python
```shell
Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12)
[GCC 4.0.1 ( Apple Inc . build 5465)] on darwin
Type "help" , "copyright" , "credits" or "license" for more information
@ -201,9 +204,9 @@ True
True
```
## 2.8 读写文件
## (8)读写文件
### 2.8.1 读写文件的基本操作
- **close** - 关闭文件,就像编辑器中的 “文件->另存为”一样。
- **read** - 读取文件内容。你可以把读取结果赋给一个变量。
@ -212,9 +215,9 @@ True
- **write('stuff')** - 给文件写入一些“东西”。
- **seek(0)** - 把读/写的位置移到文件最开头。
这些都是你需要知道的一些非常重要的命令。其中一些要用到参数,但是我们暂且不去重点关注。你只需要记住 `write` 命令需要你提供一个你要写入的文件的字符串参数。
&emsp;&emsp;这些都是你需要知道的一些非常重要的命令。其中一些要用到参数,但是我们暂且不去重点关注。你只需要记住`write`命令需要你提供一个你要写入的文件的字符串参数。
让我们用这些命令做一个小小的编辑器:
&emsp;&emsp;让我们用这些命令做一个小小的编辑器:
```python
1 from sys import argv
@ -252,13 +255,11 @@ True
33 target.close()
```
这真是一个很大的文件,可能是你输入过的最大的文件了。所以慢一点,写完检查一下,然后再运行。你也可以写一点运行一点,比如先运行 1-8 行,然后再多运行 5 行,然后再多几行,直到所有的都完成和运行了。
&emsp;&emsp;这真是一个很大的文件,可能是你输入过的最大的文件了。所以慢一点,写完检查一下,然后再运行。你也可以写一点运行一点,比如先运行 1-8 行,然后再多运行 5 行,然后再多几行,直到所有的都完成和运行了。
#### 你应该看到
&emsp;&emsp;事实上你应该看到两样东西,首先是你新脚本的输出结果:
事实上你应该看到两样东西,首先是你新脚本的输出结果:
```pyhton
```text
$ python3.6 ex16.py test.txt We're going to erase test.txt.
If you don't want that, hit CTRL-C (^C). If you do want that, hit RETURN.
?
@ -272,54 +273,59 @@ I'm going to write these to the file.
And finally, we close it.
```
现在,用编辑器打开你创建的文件(比如我的是 test.txt检查一下是不是对的。
&emsp;&emsp;现在,用编辑器打开你创建的文件(比如我的是 test.txt检查一下是不是对的。
### 附加练习
1. 如果你理解不了这个练习,回过头去按照给每行加注释的方法再过一遍,注释能帮助你理解每一行的意思,至少让你知道你不理解的地方在哪里,然后动手去查找答案。
2. 写一个类似于上个练习的脚本,使用 `read``argv` 来读取你刚刚创建的文件。
3. 这个练习中有太多的重复,试着用一个 `target.write()` 命令来打印 line1、line2、line3你可以使用字符串、格式字符串和转义字符。
4. 弄明白为什么我们要用一个 `'w'` 作为一个额外的参数来打开。提示:通过明确说明你想要写入一个文件,来安全地打开它。
5. 如果你用 `w` 模式打开文件,那你还需要 `target.truncate()` 吗? 读一读 Python 的 open 函数文件,来搞明白这个问题。
#### 练习1
### 常见问题
&emsp;&emsp;如果你理解不了这个练习,回过头去按照给每行加注释的方法再过一遍,注释能帮助你理解每一行的意思,至少让你知道你不理解的地方在哪里,然后动手去查找答案。
**`truncate()` 对于 `'w'` 参数来说是必须的吗?** 详见附加练习 5。
#### 练习2
**`'w'` 到底是什么意思?** 它真的只是一个有字符的字符串,来表示文件的一种模式。如果你用了 `'w'` ,就代表你说“用 write 模式打开这个文件。此外还有 `'r'` 表示 read 模式,`'a'` 表示增补模式后面还可能加一些修饰符modifiers
&emsp;&emsp;写一个类似于上述读取文件的练习代码,使用`read`和`argv`来读取你刚刚创建的文件
**我能对文件使用哪些修饰符?** 目前最重要的一个就是 `+` ,你可以用 `'w+'` `'r+'` 以及 `'a+'`。这样会让文件以读和写的模式打开,取决于你用的是那个符号以及文件所在的位置等。
#### 练习3
**如果只输入 `open(filename)` 是不是就用 `'r'` (读)模式打开?** 是的,那是 `open()` 函数的默认值
&emsp;&emsp;这个练习中有太多的重复,试着用一个`target.write()`命令来打印 line1、line2、line3你可以使用字符串、格式字符串和转义字符
### 读写文件方法与经验总结
#### 练习4
```
&emsp;&emsp;弄明白为什么我们要用一个`w`作为一个额外的参数来打开。提示:通过明确说明你想要写入一个文件,来安全地打开它。
#### 练习5
&emsp;&emsp;如果你用`w`模式打开文件,那你还需要`target.truncate()`吗?读一读 Python 的 open 函数文件,来搞明白这个问题。
### 2.8.2 常见问题
1. **`truncate()` 对于 `w` 参数来说是必须的吗?** 详见附加练习5。
2. **`w` 到底是什么意思?** 它真的只是一个有字符的字符串,来表示文件的一种模式。如果你用了`w` ,就代表用`write`模式打开这个文件。此外还有`r`表示 read 模式,`a`表示增补模式后面还可能加一些修饰符modifiers
3. **我能对文件使用哪些修饰符?** 目前最重要的一个就是 `+` ,你可以用`w+`、`r+`以及`a+`。这样会让文件以读和写的模式打开,取决于你用的是那个符号以及文件所在的位置等。
4. **如果只输入 `open(filename)` 是不是就用 `r` (读)模式打开?** 是的,那是`open()`函数的默认值。
### 2.8.3 读写文件方法与经验总结
```python
my_text = "今天又是一周的开始,打起精神认真赚钱不含参"
with open("path", "w", encoding="utf-8") as f:
f.write(my_text)
```
写入数据的时候最好是指定一下文件的编码方式不然下次读取的时候可能就读取不了了出现乱码。经常遇到的问题是中文的保存会以各种各样的编码方式保存。但其实在读取的时候选择对应的编码方式仍旧可以打开但直接保存为utf-8一劳永逸。特别是使用pandas将含有中文数据的DataFrame对象保存为csv文件的时候有一个具体的编码方式需要指定。
1. 写入数据的时候最好是指定一下文件的编码方式,不然下次读取的时候可能就读取不了(出现乱码)。经常遇到的问题是中文的保存,会以各种各样的编码方式保存。但其实在读取的时候选择对应的编码方式仍旧可以打开但直接保存为`utf-8`一劳永逸。特别是使用pandas将含有中文数据的DataFrame对象保存为csv文件的时候有一个具体的编码方式需要指定。
2. 其次如果是爬取的图片类型的数据,此时的写入方式就需要更改为二进制方式保存,也是之前困扰过的问题。
3. 如果爬取的文本中含有`emoji`而且准备写入MySQL中需要更改MySQL数据库的编码方式为`utf-8mb4`格式不然会出现问题。MySQL数据库的版本也有要求具体5.10以上应该都可以。
4. 数据的存写最好是使用`with open() as f`这种形式,上下文管理器会自动帮你读取完数据后关闭文件。不然在报错后寻找问题的原因真的很麻烦,一个小问题可能要找很久也找不到(真实经历)。
5. 如果遇到一个不确定是什么编码方式的文档,最好的方式是以`txt`方式打开该文件,可以看到文件的编码方式,此时也可以另存为的时候将编码方式改为自己需要的合适的编码方式。
6. 大文件的读写很浪费时间,而且对于内存的负担也很大。此时可以对数据进行分页读取比较合适,内存毕竟有限。`pickle`和`json`可以将数据存储为二进制文件和通用的json格式文件。可能需要注意的地方就是`dump`和`dunps`以及`load`和`loads`的区别。这个真的是一直没注意,每次都随机试,反正只最多需要试两下就可以,多试几次就知道了。`pickle`保存的`.pkl`文件内存小,读取快。`json`文件的引号也需要注意一下。还有就是`json`文件`load`的时候如果数据有问题就直接写正则对数据做拆分,避免所有数据都被丢失。之前遇到过`json`文件保存明明可以,但是读取就是失败的问题。后来发现是有一些字符编码有问题,会提示具体报错的代码位置,可以自行定位并一点一点的排除。网上有一个解决思路是使用一个参数,对解码进行相关的设置就可以了,但并不是万能的,至少没解决我之前遇到的问题。
7. 数据的写入读取方式:只读、只写、覆盖写等这些容易忽略的问题,幸幸苦苦将数据保存后,出现了问题,然后发现结果不对劲。回头一看才发现是数据的写入有问题,这样就很消磨热情以及浪费时间。
其次如果是爬取的图片类型的数据此时的写入方式就需要更改为二进制方式保存,也是之前困扰过的问题。
#### 解决问题的思路
如果爬取的文本中含有emoji而且准备写入mysql中需要更改mysql数据库的编码方式为utf-8mb4格式不然会出现问题。mysql数据库的版本也有要求具体5.10以上应该都可以~
&emsp;&emsp;我不是计算机专业的,周围认识的人也没有学编程的。因此每当我遇到问题的时候就借助`baidu`、`csdn`、博客园这些。现在最主要还是谷歌要用的多,百度最差,其次`csdn`总是跳来跳去也找不到答案,博客园如果有答案的话内容感觉还可以,在`csdn`上挑来挑去,最终没找到解决办法很烦人,不过也好用。谷歌报错代码挺方便的,容易检索出来比较相似的问题。
数据的存写最好是使用with open() as f这种形式上下文管理器会自动帮你读取完数据后关闭文件。不然在报错后寻找问题的原因真的很麻烦一个小问题可能要找很久也找不到真实经历
如果遇到一个不确定是什么编码方式的文档最好的方式是以txt打开该文件可以看到文件的编码方式此时也可以另存为的时候将编码方式改为自己需要的合适的编码方式。
大文件的读写,很浪费时间而且对于内存的负担也很大。此时可以对数据进行分页读取比较合适 内存毕竟有限。pickle和json可以将数据存储为二进制文件和通用的json格式文件。可能需要注意的地方就是dump和dunps以及load和loads的区别。这个真的是一直没注意每次都随机试反正只最多需要试两下就可以多试几次就知道了。pickle保存的.pkl文件内存小读取快。真的非常和json文件的引号需要注意一下。还有就是json文件load的时候如果数据有问题就直接写正则对数据做拆分避免所有数据都被丢失。之前遇到过json文件保存明明可以但是读取就是失败的问题。后来发现是有一些字符编码有问题会具体报错的那个位置可以自行定位一点一点的排除。网上有一个解决思路是有一个参数控制解码相关的设置一下就可以了但并不是万能的至少没解决我之前遇到的问题。
数据的写入读取方式:只读,只写,覆盖写等这些容易忽略很容易将幸幸苦苦的数据保存出问题然后发现结果不对劲。回头一看才发现是数据的写入有问题,这样就很消磨热情以及浪费时间。
#### 解决问题的思路:
我不是计算机专业的周围认识的人也没有学编程的。因此每当我遇到问题的时候就借助baiducsdn博客园这些。现在最主要还是谷歌要用的多百度最差其次csdn总是跳来跳去也找不到答案博客园如果有答案的话内容感觉还可以csdn挑来挑去没找到解决办法很烦人不过也好用。谷歌报错代码挺方便的容易检索出来比较相似的问题。
更多的时候自己多试几下就能发现问题的原因,记得也更清楚一些。而且每当一个困扰很久的问题解决后的那种成就感真的很爽,有一种如释负重的感觉。
&emsp;&emsp;更多的时候自己多试几下就能发现问题的原因,记得也更清楚一些。而且,每当一个困扰很久的问题解决后的那种成就感真的很爽,有一种如释负重的感觉。

View File

@ -1,14 +1,16 @@
## (9)函数
## 2.9 函数
这是一个很大的标题。接下来我要给你介绍一下函数。每一个程序员都要一遍一遍地用到函数,思考它们的作用以及如何使用它们,但是我会给你一些最简单的解释,让你能够快速上手。
&emsp;&emsp;这是一个很大的标题,接下来我要给你介绍一下函数。每一个程序员都要一遍一遍地用到函数,思考它们的作用以及如何使用它们,但是我会给你一些最简单的解释,让你能够快速上手。
函数一般就是做以下这些事情:
&emsp;&emsp;函数一般就是做以下这些事情:
1. 它们为一些代码起名字,就像变量为字符串和数字起名字一样。
2. 它们像脚本获取 `argv` 一样获取参数arguments
2. 它们像脚本获取`argv`一样获取参数arguments
3. 通过 1 和 2 的操作,让你做一些你自己的“小脚本”或者“微命令”。
你可以通过在 Python 中使用 `def` 来创建一个函数。我会让你创建 4 个不同的函数,它们就像你的脚本一样运行,之后我还会想你展示每一个之间是如何关联的。
### 2.9.1 函数初体验
&emsp;&emsp;你可以通过在 Python 中使用`def`来创建一个函数。我会让你创建 4 个不同的函数,它们就像你的脚本一样运行,之后我还会展示每一个之间是如何关联的。
```python
1 # this one is like your scripts with argv
@ -35,28 +37,24 @@
22 print_none()
```
让我们把第一个函数拆解一下,`print_two` 这是你从创建脚本中已经学到的最熟悉的东西:
&emsp;&emsp;让我们把第一个函数拆解一下,`print_two` 这是你从创建脚本中已经学到的最熟悉的东西:
1. 首先,我们告诉 Python 我们想要用 `def` (即 define来创建一个函数。
2. 在 `def` 的同一行我们给了函数一个名字,本例中是 `print_two`,但是也可以起名叫“peanuts”花生名字没关系不过最好简短一些并且能够说明这个函数的作用。
3. 然后我们告诉它我们想要 `*args` ,它很像参数 `args` ,只不过是为函数设的,必须放在括号里面才能工作。
4. 然后我们以 `:` 结束这一行,另起一行开始缩进。
5. 在 `:` 之后缩进四个空格的所有行都是关于 `print_two` 这个函数名的。我们第一个缩进的行就是用来解包这个参数argument跟之前的脚本一样。
1. 首先,我们告诉 Python 想要用`def`(即 define来创建一个函数。
2. 在`def`的同一行我们给了函数一个名字,本例中是`print_two`但是也可以起名叫“peanuts”花生名字没关系不过最好简短一些并且能够说明这个函数的作用。
3. 然后我们告诉它我们想要`*args`,它很像参数`args`,只不过是为函数设的,必须放在括号里面才能工作。
4. 然后我们以`:`结束这一行,另起一行开始缩进。
5. 在`:`之后缩进四个空格的所有行都是关于`print_two`这个函数名的。我们第一个缩进的行就是用来解包这个参数argument跟之前的脚本一样。
6. 要表明它是如何工作的,我们把这些参数打印了出来,就像我们在脚本中所做的一样。
`print_two` 的问题是它不是创建一个函数最简单的方法。在 python 里面,我们可以跳过整个解包参数的过程,只用我们需要的 `()` 里面的名字即可,这也正是 `print_two_again` 所做的事情。
之后我们用一个参数创建了 `print_one` 这个函数。
最后我们创建了一个没有参数的函数 `print_none`
&emsp;&emsp;`print_two`的问题是它不是创建一个函数最简单的方法。在 python 里面,我们可以跳过整个解包参数的过程,只用我们需要的`()`里面的名字即可,这也正是`print_two_again`所做的事情。之后我们用一个参数创建`print_one`这个函数。最后创建了一个没有参数的函数`print_none`。
| 警告! |
| :----------------------------------------------------------- |
| 这很重要。如果你现在不太明白,别急着灰心,我们会再做几个跟函数相关的练习来进一步学习。现在当我说“函数”的时候,你就把它想象成一个“迷你脚本”,跟着做就行了。 |
| &emsp;&emsp;这很重要。如果你现在不太明白,别急着灰心,我们会再做几个跟函数相关的练习来进一步学习。现在当我说“函数”的时候,你就把它想象成一个“迷你脚本”,跟着做就行了。 |
#### 你会看到
如果你运行了,你会看到:
&emsp;&emsp;如果你运行了上述代码,就会看到:
```
arg1: Zed, arg2: Shaw
@ -65,21 +63,46 @@ arg1: First!
I got nothin'.
```
现在你已经看到了函数是如何工作的。注意你使用函数的方式就像你使用 exists、open 等其他一些“命令”一样。其实我一直在跟你卖关子,因为在 python 里面,这些“命令”就是“函数”。这意味着你可以创建你自己的命令然后在你的脚本中使用。
&emsp;&emsp;现在你已经看到了函数是如何工作的。注意使用函数的方式就像你使用`exists`、`open`等其他一些“命令”一样。其实我一直在跟你卖关子,因为在 Python 里面,这些“命令”就是“函数”。这意味着你可以创建你自己的命令然后在你的脚本中使用。
#### 附加练习
创建一个如下的函数 checklist (核查表)用于后面的练习。把这些内容写在索引卡上,一直保留到你完成所有剩余练习的时候或者当你感觉你不再需要这些索引卡的时候:
1. 你是否用 `def` 来创建函数了?
2. 你的函数名是只包含字符和 `_` (下划线)吗?
3. 你在函数名后面放 `(` (左圆括号)了吗?
4. 你在左圆括号后面放参数argument了吗参数之间是以逗号隔开的吗
5. 你的每个参数都是唯一的吗(即没有重名)?
6. 你在参数后面放 `)` (右圆括号)和 `:` (冒号)了吗?
7. 你在与这个函数相关的代码行前面加上四个空格的缩进了吗?(不能多,也不能少)
8. 你是通过另起一行不缩进来结束你的函数的吗?
##### 练习1
&emsp;&emsp;你是否用 `def` 来创建函数了?
##### 练习2
&emsp;&emsp;你的函数名是只包含字符和 `_` (下划线)吗?
##### 练习3
&emsp;&emsp;你在函数名后面放 `(` (左圆括号)了吗?
##### 练习4
&emsp;&emsp;你在左圆括号后面放参数argument了吗参数之间是以逗号隔开的吗
##### 练习5
&emsp;&emsp;你的每个参数都是唯一的吗(即没有重名)?
##### 练习6
&emsp;&emsp;你在参数后面放 `)` (右圆括号)和 `:` (冒号)了吗?
##### 练习7
&emsp;&emsp;你在与这个函数相关的代码行前面加上四个空格的缩进了吗?(不能多,也不能少)
##### 练习8
&emsp;&emsp;你是通过另起一行不缩进来结束你的函数的吗?
---
Tips
当你运行(使用或者调用)一个函数时,检查以下事项:
1. 你是通过输入函数名称来运行/调用/使用一个函数的吗?
@ -87,23 +110,23 @@ I got nothin'.
3. 你有把你想要的值放在圆括号里并用逗号隔开了吗?
4. 你是以 `)` 来结束调用这个函数的吗?
在接下来的课程中用这两个 checklist ,直到你不再需要它们为止。
---
最后,再强调以我说的“运行”run、“调用”call、“使用”use都是一个意思。
&emsp;&emsp;在接下来的课程中用这两个`checklist`,直到你不再需要它们为止。最后,再强调一我说的“运行”run、“调用”call、“使用”use都是一个意思。
#### 常见问题
**函数名称有哪些要求?**跟变量名一样,任何不以数字开头的字母、数字、下划线组合都可以。
1. **函数名称有哪些要求?** 跟变量名一样,任何不以数字开头的字母、数字、下划线组合都可以。
**`\*args` 中的 `\*` 是什么作用?**这是告诉 Python 取所有的参数给函数,然后把它们放在 `args` 里放成一列,很像你之前学的 `argv` ,只不过这个是为函数设置的。这种不常用,除非有特殊需要。
2. **`\*args` 中的 `\*` 是什么作用?** 这是告诉 Python 取所有的参数给函数,然后把它们放在`args`里放成一列,很像你之前学的`argv`,只不过这个是为函数设置的。这种不常用,除非有特殊需要。
**这部分好无聊好烦人啊。**这就对了,这说明你已经开始一边输入代码一边思考它的作用了。如果想让它不这么无聊,按照我的要求一字不差地输入进去,然后再故意打乱它们,看看你能不能修复好。
&emsp;&emsp;**这部分好无聊好烦人啊。** 这就对了,这说明你已经开始一边输入代码一边思考它的作用了。如果想让它不这么无聊,按照我的要求一字不差地输入进去,然后再故意打乱它们,看看你能不能修复好。
### 函数和变量
### 2.9.2 函数和变量
函数是一个信息量巨大的东西,但是别担心,老老实实做练习,仔仔细细核对 checklist,你最终会掌握它的。
&emsp;&emsp;函数是一个信息量巨大的东西,但是别担心,老老实实做练习,仔仔细细核对`checklist`,你最终会掌握它的。
有个小点你可能没注意到,我们会在之后进行强化:你函数里面的变量跟你脚本里面的变量没有关联。通过下面这个练习思考一下这个问题:
&emsp;&emsp;有个小点你可能没注意到,我们会在之后进行强化:你函数里面的变量跟你脚本里面的变量没有关联。通过下面这个练习思考一下这个问题:
```python
1 def cheese_and_crackers(cheese_count, boxes_of_crackers):
@ -132,13 +155,13 @@ I got nothin'.
24 cheese_and_crackers(amount_of_cheese + 100, amount_of_crackers + 1000)
```
这个练习展示了我们可以给函数 `cheese_and_crackers` 赋值的几种不同的方式,我们可以直接给它数字,或者变量,亦或是数学运算,甚至是数学运算和变量的结合。
&emsp;&emsp;这个练习展示了我们可以给函数`cheese_and_crackers`赋值的几种不同的方式,可以直接给它数字,或者变量,亦或是数学运算,甚至是数学运算和变量的结合。
从某种程度上说,函数的参数有点类似于我们给变量赋值时的 `=` 符号 。事实上,如果你可以用 `=` 来定义一个东西,你就可以把它作为参数赋给函数。
&emsp;&emsp;从某种程度上说,函数的参数有点类似于我们给变量赋值时的`=`符号 。事实上,如果你可以用`=`来定义一个东西,你就可以把它作为参数赋给函数。
#### 你会看到
你应该研究一下这个脚本的输出结果,把它和你之前的脚本输出结果对比一下。
&emsp;&emsp;你应该研究一下这个脚本的输出结果,把它和你之前的脚本输出结果对比一下。
```python
We can just give the function numbers directly:
@ -168,31 +191,37 @@ Get a blanket.
#### 附加练习
1. 回顾一遍这个脚本,然后在每一行上方加上注释,解释它的作用。
2. 从下到上阅读每一行,说出所有重要的字符。
3. 写至少一个自己设计的函数,然后用 10 种不同的方式运行它。
##### 练习1
&emsp;&emsp;回顾一遍这个脚本,然后在每一行上方加上注释,解释它的作用。
##### 练习2
&emsp;&emsp;从下到上阅读每一行,说出所有重要的字符。
##### 练习3
&emsp;&emsp;写至少一个自己设计的函数,然后用 10 种不同的方式运行它。
#### 常见问题
**运行一个函数怎么可能有 10 种不同的方式?** 爱信不信,理论上讲,任何函数都有无数种调用方式。看看你对于函数、变量以及用户输入的创造力有多强。
1. **运行一个函数怎么可能有 10 种不同的方式?** 爱信不信,理论上讲,任何函数都有无数种调用方式。看看你对于函数、变量以及用户输入的创造力有多强。
**有没有什么方法能分析函数是如何运行的,以帮助我更好地理解它?**有很多方法,但是你先试试给每行加注释这种方式。其他方法包括大声把代码读出来,或者把代码打印出来然后在上面画图,来展示它是怎么运行的。
&emsp;&emsp;**有没有什么方法能分析函数是如何运行的,以帮助我更好地理解它?** 有很多方法,但是你先试试给每行加注释这种方式。其他方法包括大声把代码读出来,或者把代码打印出来然后在上面画图,来展示它是怎么运行的。
**如果我想问用户关于 cheese 和 crackers 的数字呢?**你需要用 `int()` 来把你通过 `input()` 获取的内容转化成数值。
2. **如果我想问用户关于`cheese`和`crackers`的数字呢?** 你需要用`int()`来把通过`input()`获取的内容转化成数值。
**在函数中创建 `amount_of_cheese` 这个变量会改变 `cheese_count` 这个变量吗?** 不会的,这些变量是相互独立并存在于函数之外的。它们之后会传递给函数,而且是“暂时版”,只是为了让函数运行。当函数退出之后,这些暂时的变量就会消失,其他一切正常运行。接着往下学,你会慢慢明白的。
3. **在函数中创建`amount_of_cheese`这个变量会改变`cheese_count`这个变量吗?** 不会的,这些变量是相互独立并存在于函数之外的。它们之后会传递给函数,而且是“暂时版”,只是为了让函数运行。当函数退出之后,这些暂时的变量就会消失,其他一切正常运行。接着往下学,你会慢慢明白的。
**像 `amount_of_cheese` 这样的全局变量(`global variables`)跟函数变量同名的话是不是不太好?**是的,如果这样的话,你就不知道说的到底是哪个变量了。不过有时候可能不得不用同样的名字,或者可能不小心同名了,不管怎么样,尽量避免这种情况。
4. **像`amount_of_cheese`这样的全局变量(`global variables`)跟函数变量同名的话是不是不太好?** 是的,如果这样的话,你就不知道说的到底是哪个变量了。不过有时候可能不得不用同样的名字,或者可能不小心同名了,不管怎么样,尽量避免这种情况。
**一个函数里包含的参数有数量限制吗?**这取决于 Python 的版本以及你的电脑,但是这个数量其实相当大。实践中一个函数包含 5 个参数为宜,再多就比较难用了。
5. **一个函数里包含的参数有数量限制吗?** 这取决于 Python 的版本以及你的电脑,但是这个数量其实相当大。实践中一个函数包含 5 个参数为宜,再多就比较难用了。
**你能在一个函数里面调用一个函数吗?**可以,在之后的练习里会创建一个小游戏,到时候就会用到这个。
6. **你能在一个函数里面调用一个函数吗?** 可以,在之后的练习里会创建一个小游戏,到时候就会用到这个。
### 函数和文件
### 2.9.3 函数和文件
记住你的函数 checklist然后在做这个练习的时候注意函数是如何和文件一起工作并发挥一些作用的。
ex20.py
&emsp;&emsp;记住你的函数`checklist`,然后在做这个练习的时候注意函数是如何和文件一起工作并发挥一些作用的。
```python
1 from sys import argv
@ -230,12 +259,11 @@ ex20.py
33 print_a_line(current_line, current_file)
```
着重注意我们是如何在每次运行 print_a_line 的时候把当前行的数字传递出去的。
&emsp;&emsp;着重注意我们是如何在每次运行`print_a_line`的时候把当前行的数字传递出去的。
#### 你会看到
```python
$ python3.6 ex20.py test.txt
```shell
First let's print the whole file:
This is line 1
@ -253,27 +281,41 @@ Let's print three lines:
#### 附加练习
1. 在每一行上方添加注释解释它的作用。
2. 每次 `print_a_line` 运行的时候,你都在传入一个 `current_line` 变量。写出每一次调用函数的时候 `current_line` 等于什么,然后找出它是如何变成`print_a_line` 里面的 `line_count` 的。
3. 找出每一个用到函数的地方,然后检查它的 `def` 确保你给出了正确的参数。
4. 在网上搜搜 `seek` 这个函数的作用。试着输入 `pydoc file`,看看你能否从这里看明白。然后试着输入 `pydoc file.seek` 再看看 `seek` 是用来干嘛的。
5. 搜一下简化符号 `+=` ,然后用 `+=` 重新写这个脚本。
##### 练习1
&emsp;&emsp;在每一行上方添加注释解释它的作用。
##### 练习2
&emsp;&emsp;每次`print_a_line`运行的时候,都在传入一个`current_line`变量。写出每一次调用函数的时候`current_line`等于什么,然后找出它是如何变成`print_a_line`里面的`line_count`的。
##### 练习3
&emsp;&emsp;找出每一个用到函数的地方,然后检查它的`def`确保你给出了正确的参数。
##### 练习4
&emsp;&emsp;在网上搜搜`seek`这个函数的作用。试着输入`pydoc file`,看看你能否从这里看明白。然后试着输入`pydoc file.seek`,再看看`seek`是用来干嘛的。
##### 练习5
&emsp;&emsp;搜一下简化符号`+=`,然后用`+=`重新写这个脚本。
#### 常见问题
**在 `print_all` 和其他函数里的 `f` 是什么东西?** `f` 是一个变量,就像你在练习 18 中函数的变量一样,只不过这次它是一个文件。文件在 Python 里面有点类似于一个老式电脑里面的磁带驱动器,或者一个 DVD 播放机。它有一个“读取头”read head你可以在文件里 `seek` (寻找)这个读取头所在的位置,然后在那里工作。每次你做 `f.seek(0)` 的时候你都会从移动到文件最开始,每次你做 `f.readline()` 的时候,你都在从文件里读取一行内容,并且把读取头移动到 `\n` 后面,也就是每行结束的地方。 我会在后面给你做更详细的解释。
1. **在`print_all`和其他函数里的`f`是什么东西?** `f`是一个变量,就像你在练习 18 中函数的变量一样,只不过这次它是一个文件。文件在 Python 里面有点类似于一个老式电脑里面的磁带驱动器,或者一个 DVD 播放机。它有一个“读取头”read head你可以在文件里`seek`(寻找)这个读取头所在的位置,然后在那里工作。每次你做`f.seek(0)`的时候,都会从移动到文件最开始,每次执行`f.readline()`的时候,都在从文件里读取一行内容,并且把读取头移动到`\n`后面,也就是每行结束的地方。我会在后面给你做更详细的解释。
**为什么 `seek(0)` 没有把 `current_line` 设置为 0** 首先,`seek()` 函数处理的是字节bytes不是行。`seek(0)` 这个代码把文件移动到 0 字节(也就是第一个字节处)。其次,`current_line` 只是一个变量并且跟这个文件没有任何实际联系。我们是在手动累加它。
2. **为什么`seek(0)`没有把`current_line`设置为0** 首先,`seek()`函数处理的是字节bytes不是行。`seek(0)` 这个代码把文件移动到0字节也就是第一个字节处。其次`current_line`只是一个变量并且跟这个文件没有任何实际联系。我们是在手动累加它。
**什么是 `+=` ** 你知道在英语里我们可以把 “it is” 写成 “it's” ,或者把 “you are” 写成“you're” 这叫缩写contraction。而 `+=` 就像 `=``+` 两种运算的缩写。也就是 `x = x + y` 就等同于 `x += y`
3. **什么是`+=`** 你知道在英语里我们可以把 “it is” 写成 “it's” ,或者把 “you are” 写成“you're” 这叫缩写contraction。而`+=`就像`=`和`+`两种运算的缩写。也就是`x = x + y`就等同于`x += y`。
**`readline()` 是怎么知道每一行在哪儿的?** `readline()` 里面的代码能够扫描文件的每个字节,当它发现一个 `\n` 字符,它就会停止扫描这个文件,然后回到它发现的地方。文件 `f` 就负责在每次调用 `readline()` 之后维持文件的当前位置,以此来保证它能阅读到每一行。
4. **`readline()`是怎么知道每一行在哪儿的?** `readline()`里面的代码能够扫描文件的每个字节,当它发现一个`\n`字符,它就会停止扫描这个文件,然后回到它发现的地方。文件`f`就负责在每次调用`readline()`之后维持文件的当前位置,以此来保证它能阅读到每一行。
**为什么文件中的行之间会有空行?** `readline()` 函数返回文件中每行最后的 `\n` 。又在 `print` 函数的结尾加上一个 `end = " "` 来避免给每行加上两个 `\n`
5. **为什么文件中的行之间会有空行?** `readline()`函数返回文件中每行最后的`\n` 。又在`print`函数的结尾加上一个`end = " "`来避免给每行加上两个`\n`。
### 函数可以返回一些东西
### 2.9.4 函数可以返回一些东西
你已经使用了 `=` 来命名变量并给变量赋予数值或字符串。接下来我会教你如何用 `=` 和一个新的 python 字符 `return` 来把函数中的变量设置为一个值。有一点需要密切注意,但是先输入如下代码:
&emsp;&emsp;你已经使用了`=`来命名变量并给变量赋予数值或字符串。接下来我会教你如何用`=`和一个新的 Python 字符`return`来把函数中的变量设置为一个值。有一点需要密切注意,但是先输入如下代码:
```python
1 def add(a, b):
@ -311,18 +353,18 @@ Let's print three lines:
33 print("That becomes: ", what, "Can you do it by hand?")
```
我们现在要做我们自己的加减乘除数学运算了。我说的要密切注意的是 `add` 函数里面的 `return a + b` ,这步做的是这些事情:
&emsp;&emsp;我们现在要做我们自己的加减乘除数学运算了。我说的要密切注意的是`add`函数里面的`return a + b`,这步做的是这些事情:
1. 我们的函数是以两个参数被调用的: `a` `b`
2. 我们把函数所做的事情打印出来,在本例中是 “ADDING”。
3. 然后我们让 Python 做一些反向的事情:我们返回 `a + b` 的和。你可以这样描述:我用 `a` 加上 `b` ,然后返回它们的结果。
4. Python 把这两个数加起来。然后当函数终止的时候,运行了这个函数的任何一行都能够将 `a + b` 的结果赋予一个变量。
1. 我们的函数是以两个参数被调用的:`a`和`b`。
2. 我们把函数所做的事情打印出来在本例中是“ADDING”。
3. 然后我们让 Python 做一些反向的事情:我们返回`a + b`的和。你可以这样描述:我用`a`加上`b`,然后返回它们的结果。
4. Python 把这两个数加起来。然后当函数终止的时候,运行了这个函数的任何一行都能够将`a + b`的结果赋予一个变量。
和这本书里其他内容比起来,这块你确实应该把节奏放慢一些,把代码打乱,然后试着琢磨一下每一步都发生了什么。
&emsp;&emsp;和本项目的其他内容比起来,这块你确实应该把节奏放慢一些,把代码打乱,然后试着琢磨一下每一步都发生了什么。
#### 你会看到
```python
```shell
Let's do some math with just functions!
ADDING 30 + 5
SUBTRACTING 78 - 4
@ -340,20 +382,31 @@ Can you do it by hand?
#### 附加练习
1. 如果你还不能真正理解 `return` 是干什么的,试着写几个你自己的函数,并且让它们返回一些值。你可以让它 `return` 任何东西,只要你把它们放在 `=` 右边即可。
2. 脚本的最后是一个难题。我在用一个函数的返回值作为另一个函数的参数这是在一个链chain里面进行的这样就用函数创建了一个公式。它看起来确实很难但是如果你运行这个脚本你就可以看到结果。你要做的就是试着弄明白创建同样操作的平常的函数是什么样的。
3. 一旦你有了可以解出这个难题的公式,试着对函数的某些部分做做改动,看看会发生什么。有意改动一些数让它产生一些不同的值。
4. 做相反的操作。写一个简单的公式,然后用同一种方式通过函数来计算它。
##### 练习1
这个练习可能真的很让你头大,但是放松,慢点学,把它当成是一个小游戏。正是解决这样的难题让编程如此有趣,所以之后我还会再给你一些小问题让你解决。
&emsp;&emsp;如果你还不能真正理解`return`是干什么的,试着写几个你自己的函数,并且让它们返回一些值。你可以让它`return`任何东西,只要你把它们放在`=`右边即可。
##### 练习2
&emsp;&emsp;脚本的最后是一个难题。我在用一个函数的返回值作为另一个函数的参数这是在一个链chain里面进行的这样就用函数创建了一个公式。它看起来确实很难但是如果你运行这个脚本你就可以看到结果。你要做的就是试着弄明白创建同样操作的平常的函数是什么样的。
##### 练习3
&emsp;&emsp;一旦你有了可以解出这个难题的公式,试着对函数的某些部分做做改动,看看会发生什么。有意改动一些数让它产生一些不同的值。
##### 练习4
&emsp;&emsp;做相反的操作。写一个简单的公式,然后用同一种方式通过函数来计算它。
&emsp;&emsp;这个练习可能真的很让你头大,但是放松,慢点学,把它当成是一个小游戏。正是解决这样的难题让编程如此有趣,所以之后我还会再给你一些小问题让你解决。
#### 常见问题
**为什么 python 是“从后往前”backward打印公式或者函数的** 它其实不是从后往前它是从里到外inside out。当你开始把代码打乱成分开的公式和函数时你会看到它是如何工作的。试着理解我说的 “inside out” 而不是 “backward” 。
1. **为什么 python 是“从后往前”backward打印公式或者函数的** 它其实不是从后往前它是从里到外inside out。当你开始把代码打乱成分开的公式和函数时你会看到它是如何工作的。试着理解我说的 “inside out” 而不是 “backward” 。
**我如何使用 `input()` 来输入我自己的值?**还记得 `int(input())` 吗?这样做的问题是你不能输入浮点数,所以试着用 `float(input())` 来代替。
2. **我如何使用`input()`来输入我自己的值?** 还记得`int(input())`吗?这样做的问题是你不能输入浮点数,所以试着用`float(input())`来代替。
**你说的“写一个公式”是什么意思?** 先试试 `24 + 34 / 100 - 1023` 吧,变成使用函数来计算。然后自己想出一个类似的数学公式,要用变量让它看起来更像一个公式。
3. **你说的“写一个公式”是什么意思?** 先试试`24 + 34 / 100 - 1023`吧,变成使用函数来计算。然后自己想出一个类似的数学公式,要用变量让它看起来更像一个公式。

View File

@ -1,17 +1,15 @@
# 3、编程习惯养成与思维
## 3.1 防御性编程与备注
### 防御性编程的基本思想
## 1防御性编程与备注
防御性编程的基本思想
假设A如果您从用户那里获得输入他们不一定会提供您所要求的输入因此如果您要求的是正数请不要指望他们给你一个
然后是假设B如果您正在使用一个由不完美的程序员编写的程序也许是我或者您自己那个程序中可能有错误所以您编写程序的假设是不仅用户可能会犯错程序的其他部分也可能会犯错并且您只是在假设您宁愿发现某些事情出错然后让它出错的假设下进行了许多不同的测试不知道问题的来源
但记住的主要事情是:人们是愚蠢的一般原则,并会犯错
因此您编写程序的目的是避免在犯这些错误时发生灾难
要养成编写防御性编码的习惯
&emsp;&emsp;假设A如果你从用户那里获得输入他们不一定会提供你所要求的输入因此如果要求的是正数请不要指望他们给你一个。然后是假设B如果你正在使用一个由不完美的程序员编写的程序也许是我或者你自己那个程序中可能有错误所以你编写程序的假设是不仅用户可能会犯错程序的其他部分也可能会犯错并且只是在假设宁愿发现某些事情出错然后让它出错的假设下进行了许多不同的测试不知道问题的来源 ,但记住的主要事情是:人们是愚蠢的一般原则,并会犯错。因此你编写程序的目的是避免在犯这些错误时发生灾难 ,要养成编写防御性编码的习惯。
### 防御性编程样例:
&emsp;&emsp;假设想找到某个整数的所有除数,我想弄清楚所有的除数是什么,并在循环中间打印出来,代码如下:
#### 防御性编程样例:
假设我想找到某个整数的所有除数,我想弄清楚所有的除数是什么,选择了在循环中间打印出来。
```python
x = 10
i = 1
@ -21,69 +19,62 @@ while i<x:
i= i+1
```
## 3.2 科学分析思维
## 2科学分析思维
### 迭代问题逻辑
1、选择一个可以计数的变量Choose variable that "count"
2、在外部需要初始化它Initiative outside the loop
3、需要设置正确的最终测试Setup and test
4、构建代码块Conctract block
5、当结束后你知道当我完成后我该怎么做(What to do when done)
1. 选择一个可以计数的变量Choose variable that "count"
2. 在程序外部初始化它Initiative outside the loop
3. 需要设置正确的最终测试Setup and test
4. 构建代码块Conctract block
5. 当结束并完成后,该如何去做 What to do when done
### 代码效率
因为目前需要解决问题的增长速度高于电脑计算速度的增长
在时间、空间恒定的情况下,需要考虑的是
1、计算需要多少内存
2、输入大小的函数所需的基本步骤数量是多少
&emsp;&emsp;因为目前需要解决问题的增长速度高于电脑计算速度的增长,在时间、空间一定的情况下,需要考虑的是:
1. 计算需要多少内存
2. 输入大小的函数所需的基本步骤数量是多少
| 表现 | 所需步骤与内存 |
|--|--|
| Best|min
Worst |max
| Expected| avg
## 3图灵完备语言
图灵完备语言包含三部分
1、数据数组字符串布尔
2、操作数字运算如+-and/or等
3、命令赋值、输入/输出、条件/分支、循环机制
有了这三部分,我们就可以做任何事情,在基础部分,我们都有接触过。能做什么事情呢?包括自然语言学习,图像识别,语音识别等
## 4Debugger
Debugging的思路debugging的目标是朝着没有错误的程序进行运行做这个最好的两个工具是打印和阅读代码带着怀疑的眼光看
首先要发现产生问题的最小输入,然后进行打印测试,采用二分法进行测试,每次是在代码中进行打印,每次测试可以排除一半的代码块,并自己先预测一下结果会是什么,耐心冷静的减小搜索出现问题的地方
还可以请教别人,在请教别人的时候,自己会把问题逻辑整理清楚再去问,有时候在问的时候,问了一下,自己就会恍然大悟,原来是这样
## 5抽象化、模块化、封装代码
这部分是为了解决阅读代码的问题事实上几十万行的代码看的时候很难去理解会把代码进行分成几个模块一个模块负责对应相关的操作也方便后续的debugger和阅读
例如机器学习中会分为数据清洗、训练、测试,三个大模块
## 6如何知道运行代码的时间
经过基础部分的学习大家已经了解到运行不同的代码是需要不一样的时间的
影响代码运行时间会受到1、机器性能。2、使用的语言。3、数据量。等
其实这些并不能为我们预估出运行代码的时间,因为这些都有很多变量,其实唯一不变的是运行这个程序需要多少步,
举个例子,魔方复原,在复原魔方的时候,如果一开始不知道怎么复原,没有思惟逻辑进行复原,可能需要的时间需要很久
但是通过查阅相关资料和思考,可以分为几个步骤,就可以顺利复原
所以运行代码的时间在与你知道你的代码需要运行多少步,思考的逻辑决定了你的运行代码时间
## 7如何修复他人的代码
在编程的时候,我们常常会借鉴别人的代码,但会碰到一个问题,并不是每一份代码都可以完整复现,会受到版本、运行环境等的影响,所以要修复他人的代码,提供一个思路
是要有一个系统性的思考
1、保持记录你尝试的方式、修改的地方
2、考虑重新假设
3、调试代码
4、放下自己的骄傲寻找他人的帮助
5、离开一段时间再回来修复
| :---: | :---: |
| Best| min |
Worst |max |
| Expected| avg |
## 3.3 图灵完备语言
&emsp;&emsp;图灵完备语言包含如下三部分:
1. 数据:数组,字符串,布尔
2. 操作:数字运算,如+-and/or等
3. 命令:赋值、输入/输出、条件/分支、循环机制
&emsp;&emsp;有了这三部分,我们就可以做任何事情,在基础部分,我们都有接触过。能做什么事情呢?包括自然语言学习,图像识别,语音识别等。
## 3.4 调试Debugger
&emsp;&emsp;调试的目标是朝着没有错误的程序进行运行,做这个最好的两个工具是打印和阅读代码(带着怀疑的眼光看)。首先要发现产生问题的最小输入,然后进行打印测试,采用二分法进行测试,每次是在代码中进行打印,每次测试可以排除一半的代码块,并自己先预测一下结果会是什么,耐心冷静的减小搜索出现问题的地方。还可以请教别人,在请教别人的时候,自己需要把问题逻辑整理清楚再去问,有时候通过问问题时,自己就会恍然大悟,原来是这样。
## 3.5 抽象化、模块化、封装代码
&emsp;&emsp;这部分是为了解决阅读代码的问题,事实上,几十万行的代码看的时候很难去理解,会把代码进行分成几个模块,一个模块负责对应相关的操作,也方便后续的 debugger 和代码阅读,例如机器学习中会分为数据清洗、训练、测试三个大模块。
## 3.6 如何知道运行代码的时间
&emsp;&emsp;经过基础部分的学习,大家已经了解到运行不同的代码所需的时间也不同,影响代码运行时间会受到:机器性能、使用的语言、数据量等。
&emsp;&emsp;其实这些并不能为我们预估出运行代码的时间,因为这些都有很多变量,其实唯一不变的是运行这个程序需要多少步,举个例子,在复原魔方的时候,如果一开始不知道怎么复原,没有思惟逻辑进行复原,可能需要的时间需要很久,但是通过查阅相关资料和思考,可以分为几个步骤,就可以顺利复原。
&emsp;&emsp;所以运行代码的时间在与你知道代码需要运行多少步,思考的逻辑决定了你的运行代码时间。
## 3.7 如何修复他人的代码
&emsp;&emsp;在编程的时候,我们常常会借鉴别人的代码,但会碰到一个问题,并不是每一份代码都可以完整复现,会受到版本、运行环境等的影响,所以要修复他人的代码,提供一个思路是要有一个系统性的思考,以下有几点建议:
1. 保存记录你尝试的方式、修改的地方
2. 考虑重新假设
3. 调试代码
4. 放下自己的骄傲,寻找他人的帮助
5. 离开一段时间再回来修复代码

View File

@ -1,6 +1,9 @@
## 4、FOR、IF以及while
### IF语句
#### IF
## 4 FOR、IF以及while
### 4.1 IF语句
#### 4.1.1 IF语句的使用
```python
1 people = 20
2 cats = 30
@ -32,49 +35,70 @@
28 if people == dogs:
29 print("People are dogs.")
```
运行结果
```python
&emsp;&emsp;上述代码的运行结果:
```shell
Too many cats! The world is doomed!
The world is dry!
People are greater than or equal to dogs.
People are less than or equal to dogs.
People are dogs.
```
#### 附加练习
在附加练习中,试着猜猜 if 语句是什么以及它是干什么的。在继续进行下个练习之前,试着用自己的话回答以下这些问题,
1、你认为 if 对它下面的代码起什么作用?
2、为什么 if 下面的代码要缩进 4 个空格?
3、如果没有缩进会发生什么
4、你能把一些布尔表达式放进 if 语句吗?试试看。
5、如果你改变 peoplecats 和 dogs 的初始值会发生什么?
#### 常见问题
+= 是什么意思? x += 1 就相当于 x = x + 1 但是输入的内容更少。你可以把它叫做“累加”increment by运算符。之后你还会学到 -= 这样类似的表达。
#### Else 和 if
在上个练习中你学到了一些 if 语句,思考了它的含义和作用。在你学习更多内容之前,我会解释一下上个附加练习中的问题。首先确定你做了那些练习。
##### 附加练习
1. 你认为 if 对它下面的代码起什么作用?
在附加练习中,试着猜猜`if`语句是什么以及它是干什么的。在继续进行下个练习之前,试着用自己的话回答以下这些问题:
if 语句在代码中创建了一个“分支”branch有点类似于在一本冒险书中你选择了哪个答案就翻到对应的一页如果你选择了不同的答案就会去到不同的地方。if 语句就是告诉脚本,如果这个布尔表达式是 True那就运行它下面的代码否则的话就跳过。
###### 练习1
2. 为什么 if 下面的代码要缩进 4 个空格
&emsp;&emsp;你认为`if`对它下面的代码起什么作用?
通过一行代码结尾的冒号告诉 Python 你在创建一个新的代码块,然后缩进四个空格告诉 Python 这个代码块中都有些什么。这就跟本书前半部分中你学的函数是一样的。
###### 练习2
&emsp;&emsp;为什么`if`下面的代码要缩进 4 个空格?
###### 练习3
&emsp;&emsp;如果没有缩进会发生什么?
###### 练习4
&emsp;&emsp;你能把一些布尔表达式放进`if`语句吗?试试看。
###### 练习5
&emsp;&emsp;如果你改变`people`、`cats`和`dogs`的初始值会发生什么?
##### 常见问题
&emsp;&emsp;`+=`是什么意思? `x += 1`就相当于`x = x + 1`但是输入的内容更少。你可以把它叫做“累加”increment by运算符。之后你还会学到`-=`这样类似的表达。
#### 4.1.2. Else 和 IF 使用
&emsp;&emsp;在上个练习中你学到了一些`if`语句,思考了它的含义和作用。在你学习更多内容之前,我会解释一下上个附加练习中的问题。首先确定你做了那些练习。
1. 你认为`if`对它下面的代码起什么作用?
&emsp;&emsp;`if`语句在代码中创建了一个“分支”branch有点类似于在一本冒险书中你选择了哪个答案就翻到对应的一页如果你选择了不同的答案就会去到不同的地方。`if`语句就是告诉脚本,如果这个布尔表达式是`True`,那就运行它下面的代码,否则的话就跳过。
2. 为什么`if`下面的代码要缩进 4 个空格?
&emsp;&emsp;通过一行代码结尾的冒号告诉 Python 你在创建一个新的代码块,然后缩进四个空格告诉 Python 这个代码块中都有些什么。这就跟本书前半部分中你学的函数是一样的。
3. 如果没有缩进会发生什么?
如果没有缩进你很可能收到一个错误提示。Python 一般会让你在一个带 的代码行下面缩进一些内容。
&emsp;&emsp;如果没有缩进你很可能收到一个错误提示。Python 一般会让你在一个带`:`的代码行下面缩进一些内容。
4. 你能把一些布尔表达式放进 if 语句吗?试试看。
4. 你能把一些布尔表达式放进`if`语句吗?试试看。
试试吧,你可以的。你可以把它们写得很复杂,不过复杂的东西一般风格都很糟糕。
&emsp;&emsp;试试吧,你可以的。你可以把它们写得很复杂,不过复杂的东西一般风格都很糟糕。
5. 如果你改变 peoplecats 和 dogs 的初始值会发生什么?
5. 如果你改变`people`、`cats`和`dogs`的初始值会发生什么?
因为你在比较数字,所以如果你改变了数字,不同的 if 语句将会得出不同的判断结果,那么下面某些代码块就有可能运行。回到练习中给这些变量一些不同的数值,然后看看你能否在脑中判断出来哪些代码块会运行。
&emsp;&emsp;因为在比较数字,所以如果改变了数字,不同的`if`语句将会得出不同的判断结果,那么下面某些代码块就有可能运行。回到练习中给这些变量一些不同的数值,然后看看你能否在脑中判断出来哪些代码块会运行。
把我的答案和你的比较一下,然后确保你真的理解了代码块的概念。这对你进行接下来的练习很重要。把下面的代码输入进去然后运行。
&emsp;&emsp;把我的答案和你的比较一下,然后确保你真的理解了代码块的概念。这对你进行接下来的练习很重要。把下面的代码输入进去然后运行。
```python
1 people = 30
@ -102,27 +126,41 @@ if 语句在代码中创建了一个“分支”branch有点类似于
23 print("Fine, let's stay home then.")
```
运行结果
&emsp;&emsp;上述代码的运行结果
```python
```shell
We should take the cars.
Maybe we could take the trucks.
Alright, let's just take the trucks.
```
##### 附加练习
1、试着猜猜 elif 和 else 的作用是什么。
2、改变 carspeople和 trucks 的数值,然后追溯每一个 if 语句,看看什么会被打印出来。
3、试试一些更复杂的布尔表达式比如cars > people 或者 trucks < cars
4、在每一行上面加上注释。
###### 练习1
&emsp;&emsp;试着猜猜`elif`和`else`的作用是什么。
###### 练习2
&emsp;&emsp;改变`cars`、`people`和`trucks`的数值,然后追溯每一个`if`语句,看看什么会被打印出来。
###### 练习3
&emsp;&emsp;试试一些更复杂的布尔表达式,比如`cars > people`或者`trucks < cars`
###### 练习4
&emsp;&emsp;在每一行上面加上注释。
##### 常见问题
如果多个 elif 块都是 True 会发生什么? Python 从顶部开始,然后运行第一个是 True 的代码块,也就是说,它只会运行第一个。
&emsp;&emsp;如果多个`elif`块都是`True`会发生什么? Python 从顶部开始,然后运行第一个是`True`的代码块,也就是说,它只会运行第一个。
#### IF嵌套使用
前面主要学习了调用函数、打印东西,但是这些基本都是直线运行下来的。你的脚本从上面开始运行,然后到底部结束。如果你用了一个函数,你可以随后再运行它,但是仍然不会有分叉需要你做决定的情况。现在你学习了 ifelse以及 elif你就可以让脚本来做决定了。
#### 4.1.3 IF嵌套使用
在上个脚本中你写出了一个简单的问问题的测试集。在这个练习中你将问用户一些问题,并基于他们的回答做决定。写下这个脚本,然后多玩几遍,把它弄明白。
&emsp;&emsp;前面主要学习了调用函数、打印东西,但是这些基本都是直线运行下来的。你的脚本从上面开始运行,然后到底部结束。如果你用了一个函数,你可以随后再运行它,但是仍然不会有分叉需要你做决定的情况。现在你学习了`if`、`else`以及`elif`,你就可以让脚本来做决定了。
&emsp;&emsp;在上个脚本中,你写出了一个简单的问问题的测试集。在这个练习中,你将问用户一些问题,并基于他们的回答做决定。写下这个脚本,然后多玩几遍,把它弄明白。
```python
1 print("""You enter a dark room with two doors.
@ -164,13 +202,16 @@ Alright, let's just take the trucks.
37 else:
38 print("You stumble around and fall on a knife and die. Good job!")
```
这里很关键的一点是你现在在 if 语句里面又放了一个 if 语句。这在创建“嵌套”nested决定的时候非常有用每一个分支指向另一个选择。
确保你理解了在 if 语句中嵌套 if 语句的理念。你可以通过做附加练习来真正掌握它。
&emsp;&emsp;这里很关键的一点是在`if`语句里面又放了一个`if`语句。这在创建“嵌套”nested的时候非常有用每一个分支指向另一个选择。
&emsp;&emsp;确保你理解了在`if`语句中嵌套`if`语句的理念。可以通过做附加练习来真正掌握它。
##### 你会看到
这是我玩这个冒险小游戏的结果,我可能玩得没那么好。
```python
&emsp;&emsp;这是我玩这个冒险小游戏的结果,我可能玩得没那么好。
```shell
You enter a dark room with two doors.
Do you go through door #1 or door #2?
> 1
@ -181,17 +222,20 @@ What do you do?
> 2
The bear eats your legs off. Good job!
```
##### 附加练习
给这个游戏加一些新内容,同时改变用户可以做的决定。尽可能地扩展这个游戏,直到它变得很搞笑。
写一个完全不同的新游戏。可能你不喜欢我的这个,你可以做一个你自己的。
&emsp;&emsp;给这个游戏加一些新内容,同时改变用户可以做的决定。尽可能地扩展这个游戏,直到它变得很搞笑。写一个完全不同的新游戏。可能你不喜欢我的这个,你可以做一个你自己的。
##### 常见问题
我能用一系列的 if 语句来代替 elif 吗?在某些情况下可以,但是取决于每个 if/else 是怎么写的。如果这样的话还意味着 Python 将会检查每一个 if-else 组合,而不是像 if-elif-else 组合那样只会检查第一个是 false 的。你可以多试几次,感受一下区别。
我如何表示一个数字的区间?有两种方式:一种是 0 < x < 10 或者 1 <= x < 10 这种传统表示方法另一种是 x 的区间是 (1, 10)
1. **我能用一系列的`if`语句来代替`elif`吗?** 在某些情况下可以,但是取决于每个`if/else`是怎么写的。如果这样的话还意味着 Python 将会检查每一个`if-else`组合,而不是像`if-elif-else`组合那样只会检查第一个是`false`的。你可以多试几次,感受一下区别。
如果我想在 if-elif-else 代码块中放更多的选择怎么办?为每种可能的选择增加更多的 elif 块。
### FOR语句
2. **我如何表示一个数字的区间?** 有两种方式:一种是`0 < x < 10`或者`1 <= x < 10`这种传统表示方法另一种是`x`的区间是`(1, 10)`。
3. **如果我想在`if-elif-else`代码块中放更多的选择怎么办?** 为每种可能的选择增加更多的`elif`块。
### 4.2 FOR语句
```python
1 the_count = [1, 2, 3, 4, 5]
@ -224,9 +268,10 @@ The bear eats your legs off. Good job!
28 for i in elements:
29 print(f"Element was: {i}")
```
##### 运行结果
```python
&emsp;&emsp;上述代码的运行结果:
```shell
This is count 1
This is count 2
This is count 3
@ -256,38 +301,50 @@ Element was: 4
Element was: 5
```
##### 附加练习
看看你是如何使用 range 的。查阅上面的 range 函数并理解掌握。
你能在第 22 行不使用 for-loop而是直接把 range(0, 6) 赋给 elements 吗?
找到 Python 文档关于列表的部分,然后读一读。看看除了 append你还能对列表做哪些操作
###### 练习1
&emsp;&emsp;看看你是如何使用`range`的。查阅上面的`range`函数并理解掌握。
###### 练习2
&emsp;&emsp;你能在第 22 行不使用`for-loop`,而是直接把`range(0, 6)`赋给`elements`吗?
###### 练习3
&emsp;&emsp;找到 Python 文档关于列表的部分,然后读一读。看看除了`append`,你还能对列表做哪些操作?
##### 常见问题
如何创建一个二维列表?可以用这种列表中的列表:[[1,2,3],[4,5,6]]
列表lists和数组arrays难道不是一个东西吗这取决于语言以及实现方法。在传统术语中列表和数组的实现方式不同。在 Ruby 中都叫做 arrays在 python 中都叫做 lists。所以我们就把这些叫做列表吧。
1. **如何创建一个二维列表?** 可以用这种列表中的列表:`[[1,2,3],[4,5,6]]`
为什么 for-loop 可以用一个没有被定义的变量?变量在 for-loop 开始的时候就被定义了,它被初始化到了每一次 loop 迭代时的当前元素中。
2. **列表lists和数组arrays难道不是一个东西吗** 这取决于语言以及实现方法。在传统术语中,列表和数组的实现方式不同。在 Ruby 中都叫做`arrays`,在 python 中都叫做`lists`。所以我们就把这些叫做列表吧
为什么 range(1, 3) 中的 i 只循环了两次而不是三次? range() 函数只处理从第一个到最后一个数,但不包括最后一个数,所以它在 2 就结束了。这是这类循环的通用做法。
3. **为什么`for-loop`可以用一个没有被定义的变量?** 变量在`for-loop`开始的时候就被定义了,它被初始化到了每一次`loop`迭代时的当前元素中
element.append() 的作用是什么?它只是把东西追加到列表的末尾。打开 Python shell 然后创建一个新列表。任何时候当你遇到类似的用法,试着多玩几次,去体会它们的作用。
4. **为什么`range(1, 3)`中的`i`只循环了两次而不是三次?** `range()`函数只处理从第一个到最后一个数,但不包括最后一个数,所以它在 2 就结束了。这是这类循环的通用做法。
5. **`element.append()`的作用是什么?** 它只是把东西追加到列表的末尾。打开 Python shell 然后创建一个新列表。任何时候当你遇到类似的用法,试着多玩几次,去体会它们的作用。
### while语句
现在我们来看一个新的循环: while-loop。只要一个布尔表达式是 Truewhile-loop 就会一直执行它下面的代码块。
### 4.3 while语句
等等,你应该能理解这些术语吧?如果我们写一行以 : 结尾的代码,它就会告诉 Python 开始一个新的代码块。我们用这种方式来结构化你的程序,以便 Python 明白你的意图。如果你还没有掌握这块内容,先回去复习一下,再做一些 if 语句、函数以及 for-loop直到你掌握为止
&emsp;&emsp;现在我们来看一个新的循环:`while-loop`。只要一个布尔表达式是`True``while-loop`就会一直执行它下面的代码块
之后我们会做一些练习来训练你的大脑读取这些结构,就像我们训练你掌握布尔表达式一样
&emsp;&emsp;等等,你应该能理解这些术语吧?如果我们写一行以`:`结尾的代码,它就会告诉 Python 开始一个新的代码块。我们用这种方式来结构化你的程序,以便 Python 明白你的意图。如果你还没有掌握这块内容,先回去复习一下,再做一些`if`语句、函数以及`for-loop`,直到你掌握为止
回到 while-loop它所做的只是像 if 语句一样的测试,但是它不是只运行一次代码块,而是在 while 是对的地方回到顶部再重复,直到表达式为 False
&emsp;&emsp;之后我们会做一些练习来训练你的大脑读取这些结构,就像我们训练你掌握布尔表达式一样
但是 while-loop 有个问题:有时候它们停不下来。如果你的目的是让程序一直运行直到宇宙的终结,那这样的确很屌。但大多数情况下,你肯定是需要你的循环最终能停下来的
&emsp;&emsp;回到`while-loop`,它所做的只是像`if`语句一样的测试,但是它不是只运行一次代码块,而是在`while`是`True`的地方回到顶部再重复,直到表达式为`False`
##### 为了避免这些问题,你得遵守一些规则:
&emsp;&emsp;但是`while-loop`有个问题:有时候它们停不下来。如果你的目的是让程序一直运行直到宇宙的终结,那这样的确很棒。但大多数情况下,你肯定是需要循环最终能停下来的。
1、保守使用 while-loop通常用 for-loop 更好一些。
2、检查一下你的 while 语句,确保布尔测试最终会在某个点结果为 False。
3、当遇到问题的时候把你的 while-loop 开头和结尾的测试变量打印出来,看看它们在做什么。
在这个练习中,你要通过以下三个检查来学习 while-loop
> **为了避免这些问题,你得遵守一些规则:**
> 1. 保守使用`while-loop`,通常用`for-loop`更好一些。
> 2. 检查一下你的`while`语句,确保布尔测试最终会在某个点结果为`False`。
> 3. 当遇到问题的时候,把你的`while-loop`开头和结尾的测试变量打印出来,看看它们在做什么。
&emsp;&emsp;在这个练习中,你要通过以下三个检查来学习`while-loop`
```python
1 i = 0
@ -308,9 +365,9 @@ element.append() 的作用是什么?它只是把东西追加到列表的末尾
16 print(num)
```
##### 运行结果
&emsp;&emsp;上述代码的运行结果:
```python
```shell
At the top i is 0
Numbers now: [0]
At the bottom i is 1
@ -338,23 +395,39 @@ The numbers:
5
```
##### 附加练习
1、把这个 while-loop 转换成一个你可以调用的函数,然后用一个变量替代 i < 6 里面的 6
2、用这个函数重新写一下这个脚本试试不同的数值。
3、再增加一个变量给这个函数的参数然后改变第 8 行的 +1让它增加的值与之前不同。
4、用这个函数重新写这个脚本看看会产生什么样的效果。
5、用 for-loop 和 range 写这个脚本。你还需要中间的增加值吗?如果不去掉这个增加值会发生什么?
任何时候你在运行程序的时候它失控了,只用按下 CTRL-C ,程序就会终止。
###### 练习1
&emsp;&emsp;把这个`while-loop`转换成一个你可以调用的函数,然后用一个变量替代`i < 6`里面的`6`
###### 练习2
&emsp;&emsp;用这个函数重新写一下这个脚本,试试不同的数值。
###### 练习3
&emsp;&emsp;再增加一个变量给这个函数的参数,然后改变第 8 行的`+1`,让它增加的值与之前不同。
###### 练习4
&emsp;&emsp;用这个函数重新写这个脚本,看看会产生什么样的效果。
###### 练习5
&emsp;&emsp;用`for-loop`和`range`写这个脚本。你还需要中间的增加值吗?如果不去掉这个增加值会发生什么?
&emsp;&emsp;任何时候你在运行程序的时候它失控了,只用按下 CTRL-C ,程序就会终止。
##### 常见问题
for-loop 和 while-loop 的区别是什么? for-loop 只能迭代(循环)一些东西的集合,而 while-loop 能够迭代循环任何类型的东西。不过while-loop 很难用对,而你通常能够用 for-loop 完成很多事情。
循环好难,我应该如何理解它们?人们不理解循环的主要原因是他们跟不上代码的运行。当一个循环运行的时候,它会过一遍代码块,到结尾之后再跳到顶部。为了直观表现这个过程,你可以用 print 打印出循环的整个过程,把 print 行写在循环的前面、顶部、中间、结尾。研究一下输出的内容,试着理解它是如何运行的。
1. **`for-loop`和`while-loop`的区别是什么?** `for-loop`只能迭代(循环)一些东西的集合,而`while-loop`能够迭代(循环)任何类型的东西。不过,`while-loop`很难用对,而你通常能够用`for-loop`完成很多事情
### 分支和函数
目前为止你已经了解了 if 语句,函数以及列表。现在是时候深入学习一下了。照例输入如下代码,看看你能否明白程序在做什么。
2. **循环好难,我应该如何理解它们?** 人们不理解循环的主要原因是他们跟不上代码的运行。当一个循环运行的时候,它会过一遍代码块,到结尾之后再跳到顶部。为了直观表现这个过程,你可以用`print`打印出循环的整个过程,把`print`行写在循环的前面、顶部、中间、结尾。研究一下输出的内容,试着理解它是如何运行的。
### 4.4 分支和函数
&emsp;&emsp;目前为止你已经了解了`if`语句,函数以及列表。现在是时候深入学习一下了。照例输入如下代码,看看你能否明白程序在做什么。
```python
1 from sys import exit
@ -436,9 +509,9 @@ for-loop 和 while-loop 的区别是什么? for-loop 只能迭代(循环)
77 start()
```
##### 运行结果
&emsp;&emsp;上述代码的运行结果:
```python
```shell
You are in a dark room.
There is a door to your right and left. Which one do you take?
> left
@ -454,23 +527,33 @@ You greedy bastard! Good job!
```
##### 附加练习
1、画一个这个游戏的流程图并指出它是如何运转的。
2、修正你的错误包括拼写和语法错误。
3、为你不理解的函数写上注释。
4、为游戏增加一些功能同时使代码更加简化。
5、这个 gold_room 让你输入数字的方式有点奇怪。这样做有哪些 bug ?你能改善我的代码吗?可以查查看 int() 的相关知识。
###### 练习1
&emsp;&emsp;画一个这个游戏的流程图,并指出它是如何运转的。
###### 练习2
&emsp;&emsp;修正你的错误,包括拼写和语法错误。
###### 练习3
&emsp;&emsp;为你不理解的函数写上注释。
###### 练习4
&emsp;&emsp;为游戏增加一些功能,同时使代码更加简化。
###### 练习5
&emsp;&emsp;这个`gold_room`让你输入数字的方式有点奇怪。这样做有哪些`bug`?你能改善我的代码吗?可以查查看`int()`的相关知识。
##### 常见问题
救命! 这个程序是怎么工作的!? 当你遇到不理解的代码时,不要着急,只要在每行代码下面写下注释,弄清楚这一行是做什么的,就很容易明白。确保你的注释和代码一样简洁。 然后要么画图,要么写一段话来描述代码是如何运行的。这样你就会理解其背后的原理。
为什么你要用 while True 这样可以构建一个无限循环。
exit(0) 是干什么用的? 在很多操作系统中,一个程序可以用 exit(0) 来结束,其中传入的数字代表是否有错误。如果你用 exit(1) 代表有 1 个错误, exit(0) 则代表程序正常退出。它不同于通常的布尔逻辑0==False因为你可以用不同的数字来表示不同的错误结果。你可以用 exit(100) 来表示与 exit(2) 或者 exit(1) 不同的错误结果。
为什么 input() 有时会被写成 input('> ') input 的参数是一个字符串,所以要在获取用户输入的内容前面加一个提示符。这里 > 也可以换成想要提示用户的文字。
1. **救命! 这个程序是怎么工作的!?** 当你遇到不理解的代码时,不要着急,只要在每行代码下面写下注释,弄清楚这一行是做什么的,就很容易明白。确保你的注释和代码一样简洁。 然后要么画图,要么写一段话来描述代码是如何运行的。这样你就会理解其背后的原理。
2. **为什么你要用`while True`** 这样可以构建一个无限循环。
3. **`exit(0)`是干什么用的?** 在很多操作系统中,一个程序可以用`exit(0)`来结束,其中传入的数字代表是否有错误。如果你用`exit(1)`代表有1个错误`exit(0)`则代表程序正常退出。它不同于通常的布尔逻辑(`0==False`),因为你可以用不同的数字来表示不同的错误结果。你可以用`exit(100)`来表示与`exit(2)`或者`exit(1)`不同的错误结果。
4. **为什么`input()`有时会被写成`input('> ')`** `input`的参数是一个字符串,所以要在获取用户输入的内容前面加一个提示符。这里`>`也可以换成想要提示用户的文字。

View File

@ -1,7 +1,9 @@
# 5、面向对象的编程
Python 是一门“面向对象的编程语言”Object Oriented Programming。这是指 Python 中有一个叫做 类class的结构能够让你用一种特定的方式结构化你的软件。通过使用类你可以让你的程序保持连贯性使用起来更清晰。至少理论上是这样。
## 5 面向对象的编程
&emsp;&emsp;Python 是一门“面向对象的编程语言”Object Oriented Programming。这是指 Python 中有一个叫做“类class”的结构能够让你用一种特定的方式结构化你的软件。通过使用类你可以让你的程序保持连贯性使用起来更清晰。至少理论上是这样。
### 5.1 类的例子
## 类的例子
```python
1 class Song(object): #class表示要创建类Song是类的名称
2
@ -26,128 +28,116 @@ Python 是一门“面向对象的编程语言”Object Oriented Programming
19 bulls_on_parade.sing_me_a_song()
```
##### 运行结果
&emsp;&emsp;上述代码的运行结果:
```python
```shell
Happy birthday to you
I don't want to get sued
So I'll stop right there
They rally around tha family
With pockets full of shells
```
##### 附加练习
1、用这个方法再写一些歌确保你明白你正在用字符列表来传歌词。
2、把歌词放在一个单独的变量里然后把这个变量放在类里面来使用。
3、如果你能搞定这些可以用它来做更多的事情。要是你现在没什么想法也别担心就试试看会发生什么。然后把它们掰开、揉碎、反复研究。
4、在网上搜搜“面向对象的编程”然后填满你的大脑。别担心你看不懂因为几乎一半的东西我也看不懂。
##### 常见问题
为什么我在类下面用 __init__ 函数或者其他函数的时候要用 self 如果你不用 self那么像 cheese = 'Frank' 这样的代码就会很含糊,计算机不知道你是指实例的 cheese 属性还是 一个叫做 cheese 的局部变量。而用 self.cheese = 'Frank' 的话就会很清晰,你是指实例的属性 self.cheese 。
### 学着去说面向对象
在这个练习中,我要教你如何去说“面向对象”。我所做的就是给你一些你需要了解的词和定义。然后我会给出一些需要填空的句子让你去理解。最后,你要完成一个大练习,从而在大脑中巩固这些句子。
#### 附加练习
##### 练习1
&emsp;&emsp;用这个方法再写一些歌,确保你明白你正在用字符列表来传歌词。
##### 练习2
&emsp;&emsp;把歌词放在一个单独的变量里,然后把这个变量放在类里面来使用。
##### 练习3
&emsp;&emsp;如果你能搞定这些,可以用它来做更多的事情。要是你现在没什么想法也别担心,就试试看会发生什么。然后把它们掰开、揉碎、反复研究。
##### 练习4
&emsp;&emsp;在网上搜搜“面向对象的编程”,然后填满你的大脑。别担心你看不懂,因为几乎一半的东西我也看不懂。
#### 常见问题
&emsp;&emsp;**为什么我在类下面用`__init__`函数或者其他函数的时候要用`self` ** 如果你不用`self`,那么像`cheese = 'Frank'`这样的代码就会很含糊,计算机不知道你是指实例的`cheese`属性还是一个叫做`cheese`的局部变量。而用`self.cheese = 'Frank'`的话就会很清晰,你是指实例的属性`self.cheese`。
### 5.2 学着去说面向对象
&emsp;&emsp;在这个练习中,我要教你如何去说“面向对象”。我所做的就是给你一些你需要了解的词和定义。然后我会给出一些需要填空的句子让你去理解。最后,你要完成一个大练习,从而在大脑中巩固这些句子。
#### 词汇训练
(注:为了方便理解,定义保留英文原文。)
class :告诉 Python 创建一个新类型的东西Tell Python to make a new type of thing
- 类class :告诉 Python 创建一个新类型的东西Tell Python to make a new type of thing
- 对象object两种含义最基本类型的东西, 任何实例。the most basic type of thing, and any instance of something.
- 实例instance :当你告诉 Python 创建一个类的时候你所得到的东西。What you get when you tell Python to create a class.
- def 你如何在类里面定义一个函数。How you define a function inside a class.
- self :在一个类的函数里面,`self`是被访问的实例/对象的一个变量。Inside the functions in a class, self is a variable for the instance/object being accessed.
- 继承inheritance 关于一个类能从另一个类那里继承它的特征的概念很像你和你的父母。The concept that one class can inherit traits from another class, much like you and your parents.
- 组合composition :关于一个类可以由其他一些类构成的概念, 很像一辆车包含几个轮子。The concept that a class can be composed of other classes as parts, much like how a car has wheels.
- 属性attribute 类所拥有的从组合那里得到的特性通常是变量。A property classes have that are from composition and are usually variables.
- is-a :一种用来表达某物继承自一种东西的表述, 就像“三文鱼是一种鱼”。A phrase to say that something inherits from another, as in a “salmon” is a “fish.”)
- has-a 一种用来表达某物是由一些东西组成或具有某种特性的表述就像“三文鱼有一个嘴巴”。A phrase to say that something is composed of other things or has a trait, as in “a salmon has-a mouth.”)
对象object两种含义最基本类型的东西, 任何实例。the most basic type of thing, and any instance of something.
实例instance :当你告诉 Python 创建一个类的时候你所得到的东西。What you get when you tell Python to create a class.
def 你如何在类里面定义一个函数。How you define a function inside a class.
self 在一个类的函数里面self 是被访问的实例/对象的一个变量。Inside the functions in a class, self is a variable for the instance/object
being accessed.
继承inheritance 关于一个类能从另一个类那里继承它的特征的概念很像你和你的父母。The concept that one class can inherit traits from another class, much like you and your parents.
组合composition :关于一个类可以由其他一些类构成的概念, 很像一辆车包含几个轮子。The concept that a class can be composed of other classes as parts, much like how a car has wheels.
属性attribute 类所拥有的从组合那里得到的特性通常是变量。A property classes have that are from composition and are usually variables.
is-a :一种用来表达某物继承自一种东西的表述, 就像“三文鱼是一种鱼”。A phrase to say that something inherits from another, as in a “salmon” is a “fish.”)
has-a 一种用来表达某物是由一些东西组成或具有某种特性的表述就像“三文鱼有一个嘴巴”。A phrase to say that something is composed of other things or has a trait, as in “a salmon has-a mouth.”)
花点时间为这些术语做一些闪词卡flash cards并记住它们虽然在你完成这个练习之前单纯的记忆没有任何意义但你必须要先了解这些基础的词汇。
&emsp;&emsp;花点时间为这些术语做一些闪词卡flash cards并记住它们虽然在你完成这个练习之前单纯的记忆没有任何意义但你必须要先了解这些基础的词汇。
#### 短语训练
接下来是一些 Python 代码片段以及右边的解释。
class X(Y)
创建一个名为 X 并继承自 Y 的类。
(“Make a class named X that is-a Y.”)
&emsp;&emsp;接下来是一些 Python 代码片段以及右边的解释。
class X(object): def __init__(self, J)
类 X 有一个带有 self 和 J 参数的 __init__ 函数。
(“class X has-a __init__ that takes self and J parameters.”)
| 代码片段 | 代码解释 |
| -------------------------------------- | ------------------------------------------------------------ |
| class X(Y) | 创建一个名为 X 并继承自 Y 的类。<br/>(“Make a class named X that is-a Y.”) |
| class X(object): def __init__(self, J) | 类 X 有一个带有 self 和 J 参数的 __init__ 函数。<br/>(“class X has-a __init__ that takes self and J parameters.”) |
| class X(object): def M(self, J) | 类 X 有一个带有 self 和 J 参数的 M 函数。<br/>(“class X has-a function named M that takes self and J parameters.”) |
| foo = X() | 设 foo 为类 X 的一个实例。<br/>(“Set foo to an instance of class X.”) |
| foo.M(J) | 从 foo 那里获取 M 函数,并用 self 和 J 参数来调用它。<br/>(“From foo, get the M function, and call it with parameters self, J.”) |
| foo.K = Q | 从 foo 那里获取 K 属性,并设它为 Q。<br/>(“From foo, get the K attribute, and set it to Q.”) |
class X(object): def M(self, J)
类 X 有一个带有 self 和 J 参数的 M 函数。
(“class X has-a function named M that takes self and J parameters.”)
&emsp;&emsp;在上述每一句中,当你看到`X`、`Y`、`M`、`J`、`K`、`Q`以及`foo`, 你可以把它们当做空格,比如,我还可以把这些句子写成:
foo = X()
设 foo 为类 X 的一个实例。
(“Set foo to an instance of class X.”)
foo.M(J)
从 foo 那里获取 M 函数,并用 self 和 J 参数来调用它。
(“From foo, get the M function, and call it with parameters self, J.”)
foo.K = Q
从 foo 那里获取 K 属性,并设它为 Q。
(“From foo, get the K attribute, and set it to Q.”)
在上述每一句中,当你看到 X, Y, M, J, K, Q, 以及 foo, 你可以把它们当做空格,比如,我还可以把这些句子写成:
1.“Make a class named ??? that is-a Y.”
1. “Make a class named ??? that is-a Y.”
(创建一个名为 ??? 的类,它继承自 Y。
2.“class ??? has-a __init__ that takes self and ??? parameters.”
2. “class ??? has-a __init__ that takes self and ??? parameters.”
(类 ??? 有一个带了 self 和 ??? 参数的 __init__。)
3.“class ??? has-a function named ??? that takes self and ??? parameters.”
3. “class ??? has-a function named ??? that takes self and ??? parameters.”
(类 ??? 有一个名为 ??? 的函数,这个函数带有 self 和 ??? 两个参数。)
4.“Set foo to an instance of class ???.”
4. “Set foo to an instance of class ???.”
(设 foo 为类 ??? 的一个实例。)
5.“From foo, get the ??? function, and call it with self=??? and parameters ???.”
5. “From foo, get the ??? function, and call it with self=??? and parameters ???.”
(从 foo 那里获取 ??? 函数,并用 self=??? 以及参数 ??? 来调用它。)
6.“From foo, get the ??? attribute, and set it to ???.”
6. “From foo, get the ??? attribute, and set it to ???.”
(从 foo 那里获取 ??? 属性,把它设为 ???。)
同样地,把这些短语写到一些闪词卡上,然后记一记。把 Python 代码片段放在正面,解释的句子放在背面,你必须每次都正确说出每一个短语的意思。不是说得类似就行,而是要一模一样。
&emsp;&emsp;同样地,把这些短语写到一些闪词卡上,然后记一记。把 Python 代码片段放在正面,解释的句子放在背面,你必须每次都正确说出每一个短语的意思。不是说得类似就行,而是要一模一样。
##### 综合训练
最后一项准备工作是把词汇训练和短语训练结合在一起,以下是训练内容:
#### 综合训练
1、做一个短语卡然后练习记忆。
&emsp;&emsp;最后一项准备工作是把词汇训练和短语训练结合在一起,以下是训练内容:
2、把它翻过来读句子如果在句子中看到词汇训练中的词汇就找到相应的词汇卡片。
3、练习记忆这些词汇卡片。
4、坚持练习要是你感到有些累就休息一下再继续。
1. 做一个短语卡然后练习记忆。
2. 把它翻过来,读句子,如果在句子中看到词汇训练中的词汇,就找到相应的词汇卡片。
3. 练习记忆这些词汇卡片。
4. 坚持练习,要是你感到有些累,就休息一下再继续。
#### 读更多代码
你现在需要继续读更多的代码,并在这些代码中复习你之前学过的短语。试着找到尽可能多的包含类的文件,然后跟着如下要求去做:
1、给出每个类的名字以及其他的类从它那里继承了什么。
&emsp;&emsp;你现在需要继续读更多的代码,并在这些代码中复习你之前学过的短语。试着找到尽可能多的包含类的文件,然后跟着如下要求去做:
2、在每个类下面列出它所拥有的函数以及它们的参数。
1. 给出每个类的名字,以及其他的类从它那里继承了什么。
2. 在每个类下面,列出它所拥有的函数以及它们的参数。
3. 列出所有它用`self`使用的属性。
4. 对于每个属性,给出它继承自哪个类。
3、列出所有它用 self 使用的属性。
&emsp;&emsp;这些练习的目的是过一遍真实的代码并试着把你学过的短语和它们的用法匹配和关联起来。如果你做足了训练你会开始看到这些匹配模式match patterns呼之欲出而不再是一些你不明白的空格或字符
4、对于每个属性给出它继承自哪个类。
### 5.3 编写一个属于自己的小游戏
这些练习的目的是过一遍真实的代码并试着把你学过的短语和它们的用法匹配和关联起来。如果你做足了训练你会开始看到这些匹配模式match patterns呼之欲出而不再是一些你不明白的空格或字符。
#### 本次的练习是编写一个属于自己的小游戏
以下是利用面向对象的编程方法写的宝可梦简单文字游戏,可以按照这个模板续写,或者根据自己的爱好更换角色和游戏方法
&emsp;&emsp;以下是利用面向对象的编程方法写的宝可梦简单文字游戏,可以按照这个模板续写,或者根据自己的爱好更换角色和游戏方法。
```python
class Pokemon:
@ -200,11 +190,4 @@ Pikachu.detail()
Charizard.detail()
Bulbasaur.detail()
Squirtle.detail()
```