Эх сурвалжийг харах

更新了第1天到第9天的文档

jackfrued 6 жил өмнө
parent
commit
e9d13db6f5

+ 2 - 0
Day01-15/01.初识Python.md

@@ -259,3 +259,5 @@ PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)
     
     turtle.mainloop()
     ```
+
+    > 提示:本章提供的代码中还有画国旗和画小猪佩奇的代码,有兴趣的读者请自行研究。

+ 59 - 54
Day01-15/02.语言元素.md

@@ -14,7 +14,7 @@
 - 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。
 - 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
 - 布尔型:布尔值只有`True`、`False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True`、`False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。
-- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的`i`换成了`j`。
+- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的`i`换成了`j`。实际上,这个类型并不能算作常用类型,大家了解下就可以了。
 
 #### 变量命名
 
@@ -54,26 +54,7 @@ print(a % b)
 print(a ** b)
 ```
 
-```Python
-"""
-使用input()函数获取键盘输入
-使用int()进行类型转换
-用占位符格式化输出的字符串
-
-Version: 0.1
-Author: 骆昊
-"""
-
-a = int(input('a = '))
-b = int(input('b = '))
-print('%d + %d = %d' % (a, b, a + b))
-print('%d - %d = %d' % (a, b, a - b))
-print('%d * %d = %d' % (a, b, a * b))
-print('%d / %d = %f' % (a, b, a / b))
-print('%d // %d = %d' % (a, b, a // b))
-print('%d %% %d = %d' % (a, b, a % b))
-print('%d ** %d = %d' % (a, b, a ** b))
-```
+在Python中可以使用`type`函数对变量的类型进行检查。程序设计中函数的概念跟数学上函数的概念是一致的,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解这个概念也不要紧,我们会在后续的章节中专门讲解函数的定义和使用。
 
 ```Python
 """
@@ -89,16 +70,14 @@ b = 12.345
 c = 1 + 5j
 d = 'hello, world'
 e = True
-print(type(a))
-print(type(b))
-print(type(c))
-print(type(d))
-print(type(e))
+print(type(a)) # <class 'int'>
+print(type(b)) # <class 'float'>
+print(type(c)) # <class 'complex'>
+print(type(d)) # <class 'str'>
+print(type(e)) # <class 'bool'>
 ```
 
-> 说明:上面的代码中用到了Python中的内置函数`type`来获得变量的数据类型,程序设计中函数的概念跟数学上函数的概念是一致的,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解这个概念也不要紧,我们会在后续的章节中专门讲解函数的定义和使用。
-
-在对变量类型进行转换时可以使用Python的内置函数。
+可以使用Python中内置的函数对变量类型进行转换。
 
 - `int()`:将一个数值或字符串转换成整数,可以指定进制。
 - `float()`:将一个字符串转换成浮点数。
@@ -106,9 +85,34 @@ print(type(e))
 - `chr()`:将整数转换成该编码对应的字符串(一个字符)。
 - `ord()`:将字符串(一个字符)转换成对应的编码(整数)。
 
+下面的代码通过键盘输入两个整数来实现对两个整数的算术运算。
+
+```Python
+"""
+使用input()函数获取键盘输入(字符串)
+使用int()函数将输入的字符串转换成整数
+使用print()函数输出带占位符的字符串
+
+Version: 0.1
+Author: 骆昊
+"""
+
+a = int(input('a = '))
+b = int(input('b = '))
+print('%d + %d = %d' % (a, b, a + b))
+print('%d - %d = %d' % (a, b, a - b))
+print('%d * %d = %d' % (a, b, a * b))
+print('%d / %d = %f' % (a, b, a / b))
+print('%d // %d = %d' % (a, b, a // b))
+print('%d %% %d = %d' % (a, b, a % b))
+print('%d ** %d = %d' % (a, b, a ** b))
+```
+
+> **说明**:上面的print函数中输出的字符串使用了占位符语法,其中`%d`是整数的占位符,`%f`是小数的占位符,`%%`表示百分号(因为百分号代表了占位符,所以带占位符的字符串中要表示百分号必须写成`%%`),字符串之后的`%`后面跟的变量值会替换掉占位符然后输出到终端中,运行上面的程序,看看程序执行结果就明白啦。
+
 ### 运算符
 
-Python支持多种运算符,下表大致按照优先级从高到低的顺序列出了所有的运算符,我们会陆续使用到它们。
+Python支持多种运算符,下表大致按照优先级从高到低的顺序列出了所有的运算符,运算符的优先级指的是多个运算符同时出现时,先做什么运算然后再做什么运算。除了我们之前已经用过的赋值运算符和算术运算符,我们稍后会陆续讲到其他运算符的使用。
 
 | 运算符                                                       | 描述                           |
 | ------------------------------------------------------------ | ------------------------------ |
@@ -129,11 +133,11 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
 
 >**说明:** 在实际开发中,如果搞不清楚运算符的优先级,可以使用括号来确保运算的执行顺序。
 
-下面的例子演示了赋值运算符和算术运算符的使用。
+下面的例子演示了赋值运算符和复合赋值运算符的使用。
 
 ```Python
 """
-赋值和算术运算符的使用
+赋值运算符和复合赋值运算符
 
 Version: 0.1
 Author: 骆昊
@@ -141,17 +145,9 @@ Author: 骆昊
 
 a = 10
 b = 3
-print(a + b) # 13
-print(a - b) # 7
-print(a * b) # 30
-print(a / b) # 3.3333333333333335
-print(a // b) # 3
-print(a ** b) # 1000
-print((a - 1) ** 0.5) # 3.0
-c = 4
-c += b # 相当于:c = c + b
-c *= a + 2 # 相当于:c = c * (a + 2)
-print(c) # 想想这个地方是多少
+a += b # 相当于:a = a + b
+a *= a + 2 # 相当于:a = a * (a + 2)
+print(a) # 想想这里会输出什么
 ```
 
 下面的例子演示了比较运算符(关系运算符)、逻辑运算符和身份运算符的使用。
@@ -164,28 +160,33 @@ Version: 0.1
 Author: 骆昊
 """
 
+flag0 = 1 == 1
 flag1 = 3 > 2
 flag2 = 2 < 1
 flag3 = flag1 and flag2
 flag4 = flag1 or flag2
-flag5 = not flag1
-print("flag1 = ", flag1) # flag1 = True
-print("flag2 = ", flag2) # flag2 = False
-print("flag3 = ", flag3) # flag3 = False
-print("flag4 = ", flag4) # flag4 = True
-print("flag5 = ", flag5) # flag5 = False
+flag5 = not (1 != 2)
+print('flag0 =', flag0) # flag0 = True
+print('flag1 =', flag1) # flag1 = True
+print('flag2 =', flag2) # flag2 = False
+print('flag3 =', flag3) # flag3 = False
+print('flag4 =', flag4) # flag4 = True
+print('flag5 =', flag5) # flag5 = False
 print(flag1 is True) # True
 print(flag2 is not False) # False
 ```
 
 ### 练习
 
-#### 练习1:华氏温度转摄氏温度。
+#### 练习1:华氏温度转换为摄氏温度。
+
+> 提示:华氏温度到摄氏温度的转换公式为:$C=(F - 32) \div 1.8$。
+
+参考答案:
 
 ```Python
 """
 将华氏温度转换为摄氏温度
-F = 1.8C + 32
 
 Version: 0.1
 Author: 骆昊
@@ -198,6 +199,8 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c))
 
 #### 练习2:输入圆的半径计算计算周长和面积。
 
+参考答案:
+
 ```Python
 """
 输入半径计算圆的周长和面积
@@ -217,6 +220,8 @@ print('面积: %.2f' % area)
 
 #### 练习3:输入年份判断是不是闰年。
 
+参考答案:
+
 ```Python
 """
 输入年份 如果是闰年输出True 否则输出False
@@ -226,9 +231,9 @@ Author: 骆昊
 """
 
 year = int(input('请输入年份: '))
-# 如果代码太长写成一行不便于阅读 可以使用\或()折行
-is_leap = (year % 4 == 0 and year % 100 != 0 or
-           year % 400 == 0)
+# 如果代码太长写成一行不便于阅读 可以使用\对代码进行折行
+is_leap = (year % 4 == 0 and year % 100 != 0) or \
+           year % 400 == 0
 print(is_leap)
 ```
 

+ 11 - 80
Day01-15/03.分支结构.md

@@ -81,7 +81,9 @@ print('f(%.2f) = %.2f' % (x, y))
 
 ### 练习
 
-#### 练习1:英制单位与公制单位互换
+#### 练习1:英制单位英寸与公制单位厘米互换。
+
+参考答案:
 
 ```Python
 """
@@ -101,45 +103,15 @@ else:
     print('请输入有效的单位')
 ```
 
-#### 练习2:掷骰子决定做什么
+#### 练习2:百分制成绩转换为等级制成绩。
 
-```Python
-"""
-掷骰子决定做什么事情
+> **要求**:如果输入的成绩在90分以上(含90分)输出A;80分-90分(不含90分)输出B;70分-80分(不含80分)输出C;60分-70分(不含70分)输出D;60分以下输出E。
 
-Version: 0.1
-Author: 骆昊
-"""
-
-from random import randint
-
-face = randint(1, 6)
-if face == 1:
-    result = '唱首歌'
-elif face == 2:
-    result = '跳个舞'
-elif face == 3:
-    result = '学狗叫'
-elif face == 4:
-    result = '做俯卧撑'
-elif face == 5:
-    result = '念绕口令'
-else:
-    result = '讲冷笑话'
-print(result)
-```
-> **说明:** 上面的代码中使用了random模块的randint函数生成指定范围的随机数来模拟掷骰子。
-
-#### 练习3:百分制成绩转等级制
+参考答案:
 
 ```Python
 """
-百分制成绩转等级制成绩
-90分以上    --> A
-80分~89分   --> B
-70分~79分	  --> C
-60分~69分   --> D
-60分以下    --> E
+百分制成绩转换为等级制成绩
 
 Version: 0.1
 Author: 骆昊
@@ -158,12 +130,13 @@ else:
     grade = 'E'
 print('对应的等级是:', grade)
 ```
-#### 练习4:输入三条边长如果能构成三角形就计算周长和面积
+#### 练习3:输入三条边长,如果能构成三角形就计算周长和面积。
+
+参考答案:
 
 ```Python
 """
-判断输入的边长能否构成三角形
-如果能则计算出三角形的周长和面积
+判断输入的边长能否构成三角形,如果能则计算出三角形的周长和面积
 
 Version: 0.1
 Author: 骆昊
@@ -182,45 +155,3 @@ else:
 ```
 > **说明:** 上面使用的通过边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。
 
-#### 练习5:个人所得税计算器。
-
-```Python
-"""
-输入月收入和五险一金计算个人所得税(2019年以前的算法)
-
-Version: 0.1
-Author: 骆昊
-"""
-
-salary = float(input('本月收入: '))
-insurance = float(input('五险一金: '))
-diff = salary - insurance - 3500
-if diff <= 0:
-    rate = 0
-    deduction = 0
-elif diff < 1500:
-    rate = 0.03
-    deduction = 0
-elif diff < 4500:
-    rate = 0.1
-    deduction = 105
-elif diff < 9000:
-    rate = 0.2
-    deduction = 555
-elif diff < 35000:
-    rate = 0.25
-    deduction = 1005
-elif diff < 55000:
-    rate = 0.3
-    deduction = 2755
-elif diff < 80000:
-    rate = 0.35
-    deduction = 5505
-else:
-    rate = 0.45
-    deduction = 13505
-tax = abs(diff * rate - deduction)
-print('个人所得税: ¥%.2f元' % tax)
-print('实际到手收入: ¥%.2f元' % (diff + 3500 - tax))
-```
->**说明:** 上面的代码中使用了Python内置的`abs()`函数取绝对值来处理`-0`的问题。

+ 23 - 8
Day01-15/04.循环结构.md

@@ -116,7 +116,11 @@ for i in range(1, 10):
 
 ### 练习
 
-#### 练习1:输入一个数判断是不是素数。
+#### 练习1:输入一个正整数判断是不是素数。
+
+> **提示**:素数指的是只能被1和自身整除的大于1的整数。
+
+参考答案:
 
 ```Python
 """
@@ -141,11 +145,13 @@ else:
     print('%d不是素数' % num)
 ```
 
-#### 练习2:输入两个正整数,计算最大公约数和最小公倍数。
+#### 练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。
+
+参考答案:
 
 ```Python
 """
-输入两个正整数计算最大公约数和最小公倍数
+输入两个正整数计算它们的最大公约数和最小公倍数
 
 Version: 0.1
 Author: 骆昊
@@ -158,6 +164,7 @@ y = int(input('y = '))
 if x > y:
     # 通过下面的操作将y的值赋给x, 将x的值赋给y
     x, y = y, x
+# 从两个数中较的数开始做递减的循环
 for factor in range(x, 0, -1):
     if x % factor == 0 and y % factor == 0:
         print('%d和%d的最大公约数是%d' % (x, y, factor))
@@ -165,29 +172,37 @@ for factor in range(x, 0, -1):
         break
 ```
 
-#### 练习3:打印三角形图案。
-
-```Python
-"""
-打印各种三角形图案
+#### 练习3:打印如下所示的三角形图案。
 
+```
 *
 **
 ***
 ****
 *****
+```
 
+```
     *
    **
   ***
  ****
 *****
+```
 
+```
     *
    ***
   *****
  *******
 *********
+```
+
+参考答案:
+
+```Python
+"""
+打印三角形图案
 
 Version: 0.1
 Author: 骆昊

+ 125 - 8
Day01-15/05.构造程序逻辑.md

@@ -1,13 +1,130 @@
 ## 构造程序逻辑
 
-分支和循环结构会帮助我们将程序中逻辑建立起来,将来我们的程序无论简单复杂,都是由顺序结构、分支结构、循环结构构成的。对于编程语言的初学者来说,首先要锻炼的是将人类自然语言描述的解决问题的步骤和方法翻译成代码的能力,其次就是熟练的运用之前学过的运算符、表达式以及最近的两个章节讲解的分支结构和循环结构的知识。有了这些基本的能力才能够通过计算机程序去解决各种各样的现实问题。所以,开始做练习吧!
+学完前面的几个章节后,我觉得有必要在这里带大家做一些练习来巩固之前所学的知识,虽然迄今为止我们学习的内容只是Python的冰山一角,但是这些内容已经足够我们来构建程序中的逻辑。对于编程语言的初学者来说,在学习了Python的核心语言元素(变量、类型、运算符、表达式、分支结构、循环结构等)之后,必须做的一件事情就是尝试用所学知识去解决现实中的问题,换句话说就是锻炼自己把用人类自然语言描述的算法(解决问题的方法和步骤)翻译成Python代码的能力,而这件事情必须通过大量的练习才能达成。
 
-### 练习清单
+我们在本章为大家整理了一些经典的案例和习题,希望通过这些例子,一方面帮助大家巩固之前所学的Python知识,另一方面帮助大家了解如何建立程序中的逻辑以及如何运用一些简单的算法解决现实中的问题。
 
-1. 寻找[“水仙花数”](https://baike.baidu.com/item/%E6%B0%B4%E4%BB%99%E8%8A%B1%E6%95%B0)。
-2. 寻找[“完美数”](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E6%95%B0/370913)。
-3. [“百钱百鸡”](https://baike.baidu.com/item/%E7%99%BE%E9%B8%A1%E7%99%BE%E9%92%B1/5857320)问题。
-4. 生成[“斐波拉切数列”](https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145)。
-5. Craps赌博游戏。
+### 经典的例子
 
-> **提示**:练习的参考答案在code/Day05目录下。
+1. 寻找**水仙花数**。
+
+   > **说明**:水仙花数也被称为超完全数字不变数、自恋数、自幂数、阿姆斯特朗数,它是一个3位数,该数字每个位上数字的立方之和正好等于它本身,例如:$1^3 + 5^3+ 3^3=153$。
+
+   ```Python
+   """
+   找出所有水仙花数
+   
+   Version: 0.1
+   Author: 骆昊
+   """
+   
+   for num in range(100, 1000):
+       low = num % 10
+       mid = num // 10 % 10
+       high = num // 100
+       if num == low ** 3 + mid ** 3 + high ** 3:
+           print(num)
+   ```
+
+   在上面的代码中,我们通过整除和求模运算分别找出了一个三位数的个位、十位和百位,这种小技巧在实际开发中还是常用的。用类似的方法,我们还可以实现将一个正整数反转,例如:将12345变成54321,代码如下所示。
+
+   ```Python
+   """
+   正整数的反转
+   
+   Version: 0.1
+   Author: 骆昊
+   """
+   
+   num = int(input('num = '))
+   reversed_num = 0
+   while num > 0:
+       reversed_num = reversed_num * 10 + num % 10
+       num //= 10
+   print(reversed_num)
+   ```
+
+2. **百钱百鸡**问题。
+
+   > **说明**:百钱百鸡是我国古代数学家[张丘建](https://baike.baidu.com/item/%E5%BC%A0%E4%B8%98%E5%BB%BA/10246238)在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?翻译成现代文是:公鸡5元一只,母鸡3元一只,小鸡1元三只,用100块钱买一百只鸡,问公鸡、母鸡、小鸡各有多少只?
+
+   ```Python
+   """
+   《百钱百鸡》问题
+   
+   Version: 0.1
+   Author: 骆昊
+   """
+   
+   for x in range(0, 20):
+       for y in range(0, 33):
+           z = 100 - x - y
+           if 5 * x + 3 * y + z / 3 == 100:
+               print('公鸡: %d只, 母鸡: %d只, 小鸡: %d只' % (x, y, z))
+   ```
+
+   上面使用的方法叫做**穷举法**,也称为**暴力搜索法**,这种方法通过一项一项的列举备选解决方案中所有可能的候选项并检查每个候选项是否符合问题的描述,最终得到问题的解。这种方法看起来比较笨拙,但对于运算能力非常强大的计算机来说,通常都是一个可行的甚至是不错的选择,而且问题的解如果存在,这种方法一定能够找到它。
+
+3. **CRAPS赌博游戏**。
+
+   > **说明**:CRAPS又称花旗骰,是美国拉斯维加斯非常受欢迎的一种的桌上赌博游戏。该游戏使用两粒骰子,玩家通过摇两粒骰子获得点数进行游戏。简单的规则是:玩家第一次摇骰子如果摇出了7点或11点,玩家胜;玩家第一次如果摇出2点、3点或12点,庄家胜;其他点数玩家继续摇骰子,如果玩家摇出了7点,庄家胜;如果玩家摇出了第一次摇的点数,玩家胜;其他点数,玩家继续要骰子,直到分出胜负。
+
+   ```Python
+   """
+   Craps赌博游戏
+   我们设定玩家开始游戏时有1000元的赌注
+   游戏结束的条件是玩家输光所有的赌注
+   
+   Version: 0.1
+   Author: 骆昊
+   """
+   from random import randint
+   
+   money = 1000
+   while money > 0:
+       print('你的总资产为:', money)
+       needs_go_on = False
+       while True:
+           debt = int(input('请下注: '))
+           if 0 < debt <= money:
+               break
+       first = randint(1, 6) + randint(1, 6)
+       print('玩家摇出了%d点' % first)
+       if first == 7 or first == 11:
+           print('玩家胜!')
+           money += debt
+       elif first == 2 or first == 3 or first == 12:
+           print('庄家胜!')
+           money -= debt
+       else:
+           needs_go_on = True
+       while needs_go_on:
+           needs_go_on = False
+           current = randint(1, 6) + randint(1, 6)
+           print('玩家摇出了%d点' % current)
+           if current == 7:
+               print('庄家胜')
+               money -= debt
+           elif current == first:
+               print('玩家胜')
+               money += debt
+           else:
+               needs_go_on = True
+   print('你破产了, 游戏结束!')
+   ```
+
+###有用的练习 
+
+1. 生成**斐波那契数列**的前20个数。
+
+   > **说明**:斐波那契数列(Fibonacci sequence),又称黄金分割数列,是意大利数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)在《计算之书》中提出一个在理想假设条件下兔子成长率的问题而引入的数列,所以这个数列也被戏称为&quot;兔子数列&quot;。斐波那契数列的特点是数列的前两个数都是1,从第三个数开始,每个数都是它前面两个数的和,形如:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...。斐波那契数列在现代物理、准晶体结构、化学等领域都有直接的应用。
+
+2. 找出10000以内的**完美数**。
+
+   > **说明**:完美数又称为完全数或完备数,它的所有的真因子(即除了自身以外的因子)的和(即因子函数)恰好等于它本身。例如:6($6=1+2+3$)和28($28=1+2+4+7+14$)就是完美数。完美数有很多神奇的特性,有兴趣的可以自行了解。
+
+3. 输出**100以内所有的素数**。
+
+   > **说明**:素数指的是只能被1和自身整除的正整数(不包括1)。
+
+上面练习的参考答案在本章对应的代码目录中,如果需要帮助请读者自行查看参考答案。

+ 9 - 1
Day01-15/06.函数和模块的使用.md

@@ -235,6 +235,8 @@ import module3
 
 #### 练习1:实现计算求最大公约数和最小公倍数的函数。
 
+参考答案:
+
 ```Python
 def gcd(x, y):
     (x, y) = (y, x) if x > y else (x, y)
@@ -249,6 +251,8 @@ def lcm(x, y):
 
 #### 练习2:实现判断一个数是不是回文数的函数。
 
+参考答案:
+
 ```Python
 def is_palindrome(num):
     temp = num
@@ -261,6 +265,8 @@ def is_palindrome(num):
 
 #### 练习3:实现判断一个数是不是素数的函数。
 
+参考答案:
+
 ```Python
 def is_prime(num):
     for factor in range(2, num):
@@ -271,6 +277,8 @@ def is_prime(num):
 
 #### 练习4:写一个程序判断输入的正整数是不是回文素数。
 
+参考答案:
+
 ```Python
 if __name__ == '__main__':
     num = int(input('请输入正整数: '))
@@ -337,7 +345,7 @@ if __name__ == '__main__':
 
 在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对[迪米特法则](https://zh.wikipedia.org/zh-hans/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B)的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在函数调用结束后依然可以访问,这时候就需要使用[闭包](https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)),这个我们在后续的内容中进行讲解。
 
-> **说明:** 很多人经常会将“闭包”一词和[“匿名函数”](https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0)混为一谈,但实际上它们是不同的概念,如果想提前了解这个概念,推荐看看[维基百科](https://zh.wikipedia.org/wiki/)或者[知乎](https://www.zhihu.com/)上对这个概念的讨论。
+> **说明:** 很多人经常会将“闭包”和[“匿名函数”](https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0)混为一谈,但实际上它们是不同的概念,如果想提前了解这个概念,推荐看看[维基百科](https://zh.wikipedia.org/wiki/)或者[知乎](https://www.zhihu.com/)上对这个概念的讨论。
 
 说了那么多,其实结论很简单,从现在开始我们可以将Python代码按照下面的格式进行书写,这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。
 

+ 18 - 6
Day01-15/07.字符串和常用数据结构.md

@@ -41,7 +41,7 @@ s2 = r'\n\\hello, world!\\\n'
 print(s1, s2, end='')
 ```
 
-Python为字符串类型提供了非常丰富的运算符,我们可以使用`+`运算符来实现字符串的拼接,可以使用`*`运算符来重复一个字符串的内容,可以使用`in`和`not in`来判断一个字符串是否包含另外一个字符串,我们也可以用`[]`和`[:]`运算符从字符串取出某个字符或某些字符,代码如下所示。
+Python为字符串类型提供了非常丰富的运算符,我们可以使用`+`运算符来实现字符串的拼接,可以使用`*`运算符来重复一个字符串的内容,可以使用`in`和`not in`来判断一个字符串是否包含另外一个字符串(成员运算),我们也可以用`[]`和`[:]`运算符从字符串取出某个字符或某些字符(切片运算),代码如下所示。
 
 ```Python
 s1 = 'hello ' * 3
@@ -377,7 +377,9 @@ print(scores)
 
 ### 练习
 
-#### 练习1:在屏幕上显示跑马灯文字
+#### 练习1:在屏幕上显示跑马灯文字。
+
+参考答案:
 
 ```Python
 import os
@@ -401,6 +403,8 @@ if __name__ == '__main__':
 
 #### 练习2:设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成。
 
+参考答案:
+
 ```Python
 import random
 
@@ -424,6 +428,8 @@ def generate_code(code_len=4):
 
 #### 练习3:设计一个函数返回给定文件名的后缀名。
 
+参考答案:
+
 ```Python
 def get_suffix(filename, has_dot=False):
     """
@@ -443,6 +449,8 @@ def get_suffix(filename, has_dot=False):
 
 #### 练习4:设计一个函数返回传入的列表中最大和第二大的元素的值。
 
+参考答案:
+
 ```Python
 def max2(x):
     m1, m2 = (x[0], x[1]) if x[0] > x[1] else (x[1], x[0])
@@ -455,7 +463,9 @@ def max2(x):
     return m1, m2
 ```
 
-#### 练习5:计算指定的年月日是这一年的第几天
+#### 练习5:计算指定的年月日是这一年的第几天。
+
+参考答案:
 
 ```Python
 def is_leap_year(year):
@@ -500,6 +510,8 @@ if __name__ == '__main__':
 
 #### 练习6:打印[杨辉三角](https://zh.wikipedia.org/wiki/%E6%9D%A8%E8%BE%89%E4%B8%89%E8%A7%92%E5%BD%A2)。
 
+参考答案:
+
 ```Python
 def main():
     num = int(input('Number of rows: '))
@@ -521,7 +533,7 @@ if __name__ == '__main__':
 
 ### 综合案例
 
-#### 案例1:双色球选号
+#### 案例1:双色球选号
 
 ```Python
 from random import randrange, randint, sample
@@ -562,7 +574,7 @@ if __name__ == '__main__':
 
 > **说明:** 上面使用random模块的sample函数来实现从列表中选择不重复的n个元素。
 
-#### 综合案例2:[约瑟夫环问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98)
+#### 综合案例2:[约瑟夫环问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98)
 
 ```Python
 """
@@ -592,7 +604,7 @@ if __name__ == '__main__':
 
 ```
 
-#### 综合案例3:[井字棋](https://zh.wikipedia.org/wiki/%E4%BA%95%E5%AD%97%E6%A3%8B)游戏
+#### 综合案例3:[井字棋](https://zh.wikipedia.org/wiki/%E4%BA%95%E5%AD%97%E6%A3%8B)游戏
 
 ```Python
 import os

+ 11 - 7
Day01-15/08.面向对象编程基础.md

@@ -1,8 +1,8 @@
 ## 面向对象编程基础
 
-活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。
+活在当下的程序员应该都听过&quot;面向对象编程&quot;一词,也经常有人问能不能用一句话解释下什么是&quot;面向对象编程&quot;,我们先来看看比较正式的说法。
 
-把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。
+&quot;把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。&quot;
 
 这样一说是不是更不明白了。所以我们还是看看更通俗易懂的说法,下面这段内容来自于[知乎](https://www.zhihu.com/)。
 
@@ -10,9 +10,9 @@
 
 > **说明:** 以上的内容来自于网络,不代表作者本人的观点和看法,与作者本人立场无关,相关责任不由作者承担。
 
-之前我们说过“程序是指令的集合”,我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,“每个人都应该学习编程”这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,“[软件危机](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%8D%B1%E6%9C%BA)”、“[软件工程](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B)”等一系列的概念开始在行业中出现。
+之前我们说过&quot;**程序是指令的集合**&quot;,我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,&quot;每个人都应该学习编程&quot;这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,&quot;[软件危机](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%8D%B1%E6%9C%BA)&quot;、&quot;[软件工程](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B)&quot;等一系列的概念开始在行业中出现。
 
-当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的“[银弹](https://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9)”,真正让软件开发者看到希望的是上世纪70年代诞生的[Smalltalk](https://zh.wikipedia.org/wiki/Smalltalk)编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的[Simula](https://zh.wikipedia.org/wiki/Simula)语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。
+当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的&quot;[银弹](https://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9)&quot;,真正让软件开发者看到希望的是上世纪70年代诞生的[Smalltalk](https://zh.wikipedia.org/wiki/Smalltalk)编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的[Simula](https://zh.wikipedia.org/wiki/Simula)语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。
 
 > **说明:** 当然面向对象也不是解决软件开发中所有问题的最后的“银弹”,所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持,Python也不例外。
 
@@ -97,7 +97,7 @@ if __name__ == "__main__":
     main()
 ```
 
-但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。
+但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是&quot;**We are all consenting adults here**&quot;。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。
 
 ```Python
 class Test:
@@ -124,11 +124,13 @@ if __name__ == "__main__":
 
 ### 面向对象的支柱
 
-面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是“隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口”。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。
+面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是&quot;隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口&quot;。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。
 
 ### 练习
 
-#### 练习1:定义一个类描述数字时钟
+#### 练习1:定义一个类描述数字时钟。
+
+参考答案:
 
 ```Python
 from time import sleep
@@ -180,6 +182,8 @@ if __name__ == '__main__':
 
 #### 练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。
 
+参考答案:
+
 ```Python
 from math import sqrt
 

+ 3 - 3
Day01-15/09.面向对象进阶.md

@@ -331,7 +331,7 @@ if __name__ == '__main__':
 
 ### 综合案例
 
-#### 案例1:奥特曼打小怪兽
+#### 案例1:奥特曼打小怪兽
 
 ```Python
 from abc import ABCMeta, abstractmethod
@@ -521,7 +521,7 @@ if __name__ == '__main__':
     main()
 ```
 
-#### 案例2:扑克游戏
+#### 案例2:扑克游戏
 
 ```Python
 import random
@@ -638,7 +638,7 @@ if __name__ == '__main__':
 
 >**说明:** 大家可以自己尝试在上面代码的基础上写一个简单的扑克游戏,例如21点(Black Jack),游戏的规则可以自己在网上找一找。
 
-#### 案例3:工资结算系统
+#### 案例3:工资结算系统
 
 ```Python
 """

+ 74 - 0
Day01-15/code/Day01/flag.py

@@ -0,0 +1,74 @@
+"""
+用Python的turtle模块绘制国旗
+"""
+import turtle
+
+
+def draw_rectangle(x, y, width, height):
+    """绘制矩形"""
+    turtle.goto(x, y)
+    turtle.pencolor('red')
+    turtle.fillcolor('red')
+    turtle.begin_fill()
+    for i in range(2):
+        turtle.forward(width)
+        turtle.left(90)
+        turtle.forward(height)
+        turtle.left(90)
+    turtle.end_fill()
+
+
+def draw_star(x, y, radius):
+    """绘制五角星"""
+    turtle.setpos(x, y)
+    pos1 = turtle.pos()
+    turtle.circle(-radius, 72)
+    pos2 = turtle.pos()
+    turtle.circle(-radius, 72)
+    pos3 = turtle.pos()
+    turtle.circle(-radius, 72)
+    pos4 = turtle.pos()
+    turtle.circle(-radius, 72)
+    pos5 = turtle.pos()
+    turtle.color('yellow', 'yellow')
+    turtle.begin_fill()
+    turtle.goto(pos3)
+    turtle.goto(pos1)
+    turtle.goto(pos4)
+    turtle.goto(pos2)
+    turtle.goto(pos5)
+    turtle.end_fill()
+
+
+def main():
+    """主程序"""
+    turtle.speed(12)
+    turtle.penup()
+    x, y = -270, -180
+    # 画国旗主体
+    width, height = 540, 360
+    draw_rectangle(x, y, width, height)
+    # 画大星星
+    pice = 22
+    center_x, center_y = x + 5 * pice, y + height - pice * 5
+    turtle.goto(center_x, center_y)
+    turtle.left(90)
+    turtle.forward(pice * 3)
+    turtle.right(90)
+    draw_star(turtle.xcor(), turtle.ycor(), pice * 3)
+    x_poses, y_poses = [10, 12, 12, 10], [2, 4, 7, 9]
+    # 画小星星
+    for x_pos, y_pos in zip(x_poses, y_poses):
+        turtle.goto(x + x_pos * pice, y + height - y_pos * pice)
+        turtle.left(turtle.towards(center_x, center_y) - turtle.heading())
+        turtle.forward(pice)
+        turtle.right(90)
+        draw_star(turtle.xcor(), turtle.ycor(), pice)
+    # 隐藏海龟
+    turtle.ht()
+    # 显示绘图窗口
+    turtle.mainloop()
+
+
+if __name__ == '__main__':
+    main()