Skip to content

Commit cf0c470

Browse files
committed
添加了新的文档
1 parent 87de712 commit cf0c470

13 files changed

+726
-2
lines changed

res/ENIAC.jpg

173 KB
Loading

res/builtin-functions.png

218 KB
Loading

res/combination.png

3.39 KB
Loading

res/equation.png

2.14 KB
Loading

res/format-string.png

98.1 KB
Loading

res/piecewise-function.png

-19.3 KB
Loading

res/qrcode.png

-567 Bytes
Loading

res/string-definition.png

2.94 KB
Loading

第004课:Python语言元素之运算符.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ print('flag5 =', flag5) # flag5 = False
9292

9393
#### 例子1:华氏温度转换为摄氏温度。
9494

95-
> **提示**:华氏温度到摄氏温度的转换公式为:$C=(F - 32) \div 1.8$
95+
> **提示**:华氏温度到摄氏温度的转换公式为:`C = (F - 32) / 1.8`
9696
9797
```Python
9898
"""

第005课:分支结构.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ else:
6767
print(f'f({x}) = {y}')
6868
```
6969

70-
> **说明:** 大家可以自己感受和评判一下这两种写法到底是哪一种更好。在**[Python之禅](https://zhuanlan.zhihu.com/p/111843067)**中有这么一句话:“Flat is better than nested”,之所以提倡代码“扁平化”是因为嵌套结构的嵌套层次如果很多,会严重的影响代码的可读性,所以能使用扁平化结构时就不要使用嵌套结构。
70+
> **说明:** 大家可以自己感受和评判一下这两种写法到底是哪一种更好。在[**Python之禅**](https://zhuanlan.zhihu.com/p/111843067)中有这么一句话:“**Flat is better than nested**”,之所以提倡代码“扁平化”是因为嵌套结构的嵌套层次如果很多,会严重的影响代码的可读性,所以能使用扁平化结构时就不要使用嵌套结构。
7171
7272
### 一些例子
7373

第008课:函数和模块.md

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
## 第008课:函数和模块
2+
3+
在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。
4+
5+
![](res/equation.png)
6+
7+
事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案,所以答案应该是$C_7^3=35$。组合数的计算公式如下所示。
8+
9+
![](res/combination.png)
10+
11+
根据我们前面学习的知识,可以用循环做累乘来计算阶乘,那么通过下面的Python代码我们就可以计算出组合数`C(M,N)`的值,代码如下所示。
12+
13+
```Python
14+
"""
15+
输入M和N计算C(M,N)
16+
17+
Version: 0.1
18+
Author: 骆昊
19+
"""
20+
m = int(input('m = '))
21+
n = int(input('n = '))
22+
# 计算m的阶乘
23+
fm = 1
24+
for num in range(1, m + 1):
25+
fm *= num
26+
# 计算n的阶乘
27+
fn = 1
28+
for num in range(1, n + 1):
29+
fn *= num
30+
# 计算m-n的阶乘
31+
fm_n = 1
32+
for num in range(1, m - n + 1):
33+
fm_n *= num
34+
# 计算C(M,N)的值
35+
print(fm // fn // fm_n)
36+
```
37+
38+
### 函数的作用
39+
40+
不知道大家是否注意到,上面的代码中我们做了三次求阶乘,虽然`m``n``m - n`的值各不相同,但是三段代码并没有实质性的区别,属于重复代码。世界级的编程大师*Martin Fowler*先生曾经说过:“**代码有很多种坏味道,重复是最坏的一种!**”。要写出高质量的代码首先要解决的就是重复代码的问题。对于上面的代码来说,我们可以将计算阶乘的功能封装到一个称之为“函数”的功能模块中,在需要计算阶乘的地方,我们只需要“调用”这个“函数”就可以了。
41+
42+
### 定义函数
43+
44+
数学上的函数通常形如`y = f(x)`或者`z = g(x, y)`这样的形式,在`y = f(x)`中,`f`是函数的名字,`x`是函数的自变量,`y`是函数的因变量;而`z = g(x, y)`中,`g`是函数名,`x``y`是函数的自变量,`z`是函数的因变量。Python中的函数跟这个结构是一致的,每个函数都有自己的名字、自变量和因变量。我们通常把Python中函数的自变量称为函数的参数,而因变量称为函数的返回值。
45+
46+
在Python中可以使用`def`关键字来定义函数,和变量一样每个函数也应该有一个漂亮的名字,命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,就是我们刚才说到的函数的自变量,而函数执行完成后我们会通过`return`关键字来返回函数的执行结果,就是我们刚才说的函数的因变量。
47+
48+
我们可以用函数的知识对上面的代码进行重构(不影响代码执行结果的前提下对代码的结构进行调整),重构之后的代码如下所示。
49+
50+
```Python
51+
"""
52+
输入M和N计算C(M,N)
53+
54+
Version: 0.1
55+
Author: 骆昊
56+
"""
57+
58+
59+
# 定义函数:def是定义函数的关键字、fac是函数名,num是参数(自变量)
60+
def fac(num):
61+
"""求阶乘"""
62+
result = 1
63+
for n in range(1, num + 1):
64+
result *= n
65+
# 返回num的阶乘(因变量)
66+
return result
67+
68+
69+
m = int(input('m = '))
70+
n = int(input('n = '))
71+
# 当需要计算阶乘的时候不用再写重复代码而是直接调用函数fac
72+
# 调用函数的语法是在函数名后面跟上圆括号并传入参数
73+
print(fac(m) // fac(n) // fac(m - n))
74+
```
75+
76+
### 函数的参数
77+
78+
#### 参数的默认值
79+
80+
在Python语言中,如果函数中没有`return`语句,那么函数默认返回代表空值的`None`。另外,在定义函数时,函数也可以没有自变量,但是函数名后面的圆括号是必须有的。Python中还允许函数的参数拥有默认值,例如我们把上一课中摇色子获得点数的功能定义到一个函数中,我们可以写出如下所示的代码。
81+
82+
```Python
83+
"""
84+
参数的默认值
85+
86+
Version: 0.1
87+
Author: 骆昊
88+
"""
89+
from random import randint
90+
91+
92+
# 定义摇色子的函数,n表示色子的个数,默认值为2
93+
def roll_dice(n=2):
94+
"""摇色子返回总的点数"""
95+
total = 0
96+
for _ in range(n):
97+
total += randint(1, 6)
98+
return total
99+
100+
101+
# 如果没有指定参数,那么n使用默认值2,表示摇两颗色子
102+
print(roll_dice())
103+
# 传入参数3,变量n被赋值为3,表示摇三颗色子获得点数
104+
print(roll_dice(3))
105+
```
106+
107+
我们再来看一个更为简单的例子。
108+
109+
```Python
110+
def add(a=0, b=0, c=0):
111+
"""三个数相加求和"""
112+
return a + b + c
113+
114+
115+
# 调用add函数,没有传入参数,那么a、b、c都使用默认值0
116+
print(add()) # 0
117+
# 调用add函数,传入一个参数,那么该参数赋值给变量a, 变量b和c使用默认值0
118+
print(add(1)) # 1
119+
# 调用add函数,传入两个参数,1和2分别赋值给变量a和b,变量c使用默认值0
120+
print(add(1, 2)) # 3
121+
# 调用add函数,传入三个参数,分别赋值给a、b、c三个变量
122+
print(add(1, 2, 3)) # 6
123+
# 传递参数时可以不按照设定的顺序进行传递
124+
print(add(c=50, a=100, b=200))
125+
```
126+
127+
#### 可变参数
128+
129+
接下来,我们还可以实现一个对任意多个数求和的`add`函数,因为Python语言中的函数支持可变参数,所谓可变参数指的是在调用函数时,可以向函数传入0个或任意多个参数。将来我们以团队协作开发的模式做商业项目时,可能需要去设计一个函数给其他人使用,但我们又不知道函数的调用者会向该函数传入多少个参数,这个时候可变参数就可以派上用场。下面的代码演示了用可变参数实现对任意多个数求和的`add`函数。
130+
131+
```Python
132+
"""
133+
可变参数
134+
135+
Version: 0.1
136+
Author: 骆昊
137+
"""
138+
139+
140+
# 在参数名前面的*表示args是一个可变参数
141+
def add(*args):
142+
total = 0
143+
# 可变参数可以放在for循环中取出每个参数的值
144+
for val in args:
145+
total += val
146+
return total
147+
148+
149+
# 在调用add函数时可以传入0个或任意多个参数
150+
print(add())
151+
print(add(1))
152+
print(add(1, 2))
153+
print(add(1, 2, 3))
154+
print(add(1, 3, 5, 7, 9))
155+
```
156+
157+
### 用模块管理函数
158+
159+
不管用什么样的编程语言来写代码,给变量、函数起名字都是一个让人头疼的问题,因为我们会遇到**命名冲突**这种尴尬的情况。最简单的场景就是在同一个`.py`文件中定义了两个同名的函数,如下所示。
160+
161+
```Python
162+
def foo():
163+
print('hello, world!')
164+
165+
166+
def foo():
167+
print('goodbye, world!')
168+
169+
170+
foo() # 大家猜猜调用foo函数会输出什么
171+
```
172+
173+
当然上面的这种情况我们很容易就能避免,但是如果项目是团队协作多人开发的时候,团队中可能有多个程序员都定义了名为`foo`的函数,这种情况下怎么解决命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过`import`关键字导入指定的模块再使用**完全限定名**的调用方式就可以区分到底要使用的是哪个模块中的`foo`函数,代码如下所示。
174+
175+
`module1.py`
176+
177+
```Python
178+
def foo():
179+
print('hello, world!')
180+
```
181+
182+
`module2.py`
183+
184+
```Python
185+
def foo():
186+
print('goodbye, world!')
187+
```
188+
189+
`test.py`
190+
191+
```Python
192+
import module1
193+
import module2
194+
195+
# 用“模块名.函数名”的方式(完全限定名)调用函数,
196+
module1.foo() # hello, world!
197+
module2.foo() # goodbye, world!
198+
```
199+
200+
在导入模块时,还可以使用`as`关键字对模块进行别名,这样我们可以使用更为简短的完全限定名。
201+
202+
`test.py`
203+
204+
```Python
205+
import module1 as m1
206+
import module2 as m2
207+
208+
m1.foo() # hello, world!
209+
m2.foo() # goodbye, world!
210+
```
211+
212+
上面的代码我们导入了定义函数的模块,我们也可以使用`from...import...`语法从模块中直接导入需要使用的函数,代码如下所示。
213+
214+
`test.py`
215+
216+
```Python
217+
from module1 import foo
218+
219+
foo() # hello, world!
220+
221+
from module2 import foo
222+
223+
foo() # goodbye, world!
224+
```
225+
226+
但是,如果我们如果从两个不同的模块中导入了同名的函数,后导入的函数会覆盖掉先前的导入,就像下面的代码中,调用`foo`会输出`hello, world!`,因为我们先导入了`module2``foo`,后导入了`module1``foo` 。如果两个`from...import...`反过来写,就是另外一番光景了。
227+
228+
`test.py`
229+
230+
```Python
231+
from module2 import foo
232+
from module1 import foo
233+
234+
foo() # hello, world!
235+
```
236+
237+
如果想在上面的代码中同时使用来自两个模块中的`foo`函数也是有办法的,大家可能已经猜到了,还是用`as`关键字对导入的函数进行别名,代码如下所示。
238+
239+
`test.py`
240+
241+
```Python
242+
from module1 import foo as f1
243+
from module2 import foo as f2
244+
245+
f1() # hello, world!
246+
f2() # goodbye, world!
247+
```
248+
249+
### 标准库中的模块和函数
250+
251+
Python标准库中提供了大量的模块和函数来简化我们的开发工作,我们之前用过的`random`模块就为我们提供了生成随机数和进行随机抽样的函数;而`time`模块则提供了和时间操作相关的函数。随着我们进一步的学习Python编程知识,我们还会用到更多的模块和函数。Python标准库中还有一类函数是不需要`import`就能够直接使用的,我们将其称之为内置函数,这些内置函数都是很有用也是最常用的,下面的表格列出了一部分的内置函数。
252+
253+
| 函数 | 说明 |
254+
| ------- | ------------------------------------------------------------ |
255+
| `abs` | 返回一个数的绝对值,例如:`abs(-1.3)`会返回`1.3`|
256+
| `bin` | 把一个整数转换成以`'0b'`开头的二进制字符串,例如:`bin(123)`会返回`'0b1111011'`|
257+
| `chr` | 将Unicode编码转换成对应的字符,例如:`chr(8364)`会返回`'€'`|
258+
| `hex` | 将一个整数转换成以`'0x'`开头的十六进制字符串,例如:`hex(123)`会返回`'0x7b'`|
259+
| `input` | 从输入中读取一行,返回读到的字符串。 |
260+
| `len` | 获取字符串、列表等的长度。 |
261+
| `max` | 返回多个参数或一个可迭代对象(后面会讲)中的最大值,例如:`max(12, 95, 37)`会返回`95`|
262+
| `min` | 返回多个参数或一个可迭代对象(后面会讲)中的最小值,例如:`min(12, 95, 37)`会返回`12`|
263+
| `oct` | 把一个整数转换成以`'0o'`开头的八进制字符串,例如:`oct(123)`会返回`'0o173'`|
264+
| `open` | 打开一个文件并返回文件对象(后面会讲)。 |
265+
| `ord` | 将字符转换成对应的Unicode编码,例如:`ord('€')`会返回`8364`|
266+
| `pow` | 求幂运算,例如:`pow(2, 3)`会返回`8``pow(2, 0.5)`会返回`1.4142135623730951`|
267+
| `print` | 打印输出。 |
268+
| `range` | 构造一个范围序列,例如:`range(100)`会产生`0``99`的整数序列。 |
269+
| `round` | 按照指定的精度对数值进行四舍五入,例如:`round(1.23456, 4)`会返回`1.2346`|
270+
| `sum` | 对一个序列中的项从左到右进行求和运算,例如:`sum(range(1, 101))`会返回`5050`|
271+
| `type` | 返回对象的类型,例如:`type(10)`会返回`int`;而` type('hello')`会返回`str`|
272+
273+
### 简单的总结
274+
275+
**函数是功能相对独立且会重复使用的代码的封装**。学会使用定义和使用函数,就能够写出更为优质的代码。当然,Python语言的标准库中已经为我们提供了大量的模块和常用的函数,用好这些模块和函数就能够用更少的代码做更多的事情。
276+
277+
> **温馨提示**:学习中如果遇到困难,可以加**QQ交流群**询问,群号:**789050736**,当然也可以看看我们为大家录制的入门视频,视频的链接地址:<https://pan.baidu.com/s/10y7sGM016YBM7gDdauGqLw>,密码:4s6r。

0 commit comments

Comments
 (0)