├── 1. Python 安装及基本语法.ipynb
├── 2. Python 数据结构.ipynb
├── 3. Python 面向对象编程.ipynb
├── 4. Python 文件与模块.ipynb
├── LICENSE
├── README.md
└── src
├── fig11.png
├── fig12.png
├── fig13.png
├── fig14.png
├── fig41.png
├── fig42.png
├── fig43.png
└── fig44.png
/1. Python 安装及基本语法.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "attachments": {},
5 | "cell_type": "markdown",
6 | "id": "cb6a5a34",
7 | "metadata": {},
8 | "source": [
9 | "# Python 安装及基本语法"
10 | ]
11 | },
12 | {
13 | "attachments": {},
14 | "cell_type": "markdown",
15 | "id": "1294ec00",
16 | "metadata": {},
17 | "source": [
18 | "Python 是一种上手简单、功能丰富的编程语言,是数据科学领域首选的可靠工具。通过 Python 你可以迅速解决问题,而不是把精力消耗在复杂的语法与编程细节上,这与本教程的核心思想“简洁”不谋而合。\n",
19 | "\n",
20 | "当全世界的数据科学家与研究人员享受 Python 带来的便利时,另一部分人正在致力于开发各种强大的 数据分析 / 机器学习 / 神经网络运行库,使得复杂的算法和模型不再成为技术门槛,越来越多的人都有机会进入数据科学领域进行学习与创新。"
21 | ]
22 | },
23 | {
24 | "attachments": {},
25 | "cell_type": "markdown",
26 | "id": "044f5e42",
27 | "metadata": {},
28 | "source": [
29 | "## 1.1.1 Python 安装运行"
30 | ]
31 | },
32 | {
33 | "attachments": {},
34 | "cell_type": "markdown",
35 | "id": "bfa93e3f",
36 | "metadata": {},
37 | "source": [
38 | "### 1.1.1.1 下载安装"
39 | ]
40 | },
41 | {
42 | "attachments": {},
43 | "cell_type": "markdown",
44 | "id": "b10fb80e",
45 | "metadata": {},
46 | "source": [
47 | "- 对于 Windows / Mac 用户,首先在官网 https://www.python.org/downloads/ 下载对应操作系统的 Python3 安装包,然后双击运行安装。\n",
48 | "\n",
49 | "- 对于Linux用户,执行 `sudo apt-get update && sudo apt-get install python3` 命令进行安装。"
50 | ]
51 | },
52 | {
53 | "attachments": {},
54 | "cell_type": "markdown",
55 | "id": "c07246c9",
56 | "metadata": {},
57 | "source": [
58 | "在安装完成后,打开命令提示符(win + R键,输入cmd回车) / 终端(command + 空格,输入term回车),执行 python3 -V 命令,若出现对应python版本号则安装成功。"
59 | ]
60 | },
61 | {
62 | "attachments": {},
63 | "cell_type": "markdown",
64 | "id": "318310ac",
65 | "metadata": {},
66 | "source": [
67 | " "
68 | ]
69 | },
70 | {
71 | "attachments": {},
72 | "cell_type": "markdown",
73 | "id": "896e8b3f",
74 | "metadata": {},
75 | "source": [
76 | "### 1.1.1.2 编辑器与解释器\n"
77 | ]
78 | },
79 | {
80 | "attachments": {},
81 | "cell_type": "markdown",
82 | "id": "c9784dc1",
83 | "metadata": {},
84 | "source": [
85 | "一个 Python 程序要经过“编写”和“运行”两个阶段。\n",
86 | "\n",
87 | "- 在编写阶段,我们通过【编辑器】完成后缀为.py程序代码的编写。\n",
88 | "- 在运行阶段,我们通过【解释器】运行编写好的程序。\n",
89 | "\n",
90 | "编辑器可以是notepad++、emeditor、甚至 windows 中最常见的 txt 编辑器。但为了提高我们的编程效率,我们往往选择功能更全面的 PyCharm 或者 vscode 等专用集成代码编辑器(IDLE)。\n",
91 | "\n",
92 | "解释器就是我们在上步安装的 python 可执行文件,在 windows 中它是 python3.exe,在 Mac / Linux 中它是名为 python3 的可执行文件。"
93 | ]
94 | },
95 | {
96 | "attachments": {},
97 | "cell_type": "markdown",
98 | "id": "ec26345b",
99 | "metadata": {},
100 | "source": [
101 | "### 1.1.1.3 第一个Python程序"
102 | ]
103 | },
104 | {
105 | "attachments": {},
106 | "cell_type": "markdown",
107 | "id": "2e400540",
108 | "metadata": {},
109 | "source": [
110 | "在成功安装后,我们将尝试编写第一个Python程序。\n",
111 | "\n",
112 | "首先我们选择 Python 自带的IDLE编辑器\n",
113 | "- Windows 在 开始 -> 程序 -> Python3. -> IDLE (Python GUI) 打开\n",
114 | "- Mac 在 启动 -> IDLE 打开,然后菜单栏 File -> New File\n",
115 | "\n",
116 | "然后输入 `print(\"hello world\")`,并保存到任意位置,我们的程序编写阶段就完成啦!"
117 | ]
118 | },
119 | {
120 | "attachments": {},
121 | "cell_type": "markdown",
122 | "id": "20c7abf3",
123 | "metadata": {},
124 | "source": [
125 | " "
126 | ]
127 | },
128 | {
129 | "attachments": {},
130 | "cell_type": "markdown",
131 | "id": "84e8484b",
132 | "metadata": {},
133 | "source": [
134 | "下一步我们尝试用解释器运行保存的.py程序。\n",
135 | "\n",
136 | "首先通过命令行输入 `cd ~/***` 进入到文件存储的位置(这里 \\*\\*\\* 是你文件储存位置的路径)\n",
137 | "\n",
138 | "然后命令行执行 `Python3 test.py` 命令,这时输出 hello world 字样则程序运行成功!"
139 | ]
140 | },
141 | {
142 | "attachments": {},
143 | "cell_type": "markdown",
144 | "id": "52a946a6",
145 | "metadata": {},
146 | "source": [
147 | " "
148 | ]
149 | },
150 | {
151 | "attachments": {},
152 | "cell_type": "markdown",
153 | "id": "04586d92",
154 | "metadata": {},
155 | "source": [
156 | "### 1.1.1.4 交互式环境"
157 | ]
158 | },
159 | {
160 | "attachments": {},
161 | "cell_type": "markdown",
162 | "id": "5c8033c5",
163 | "metadata": {},
164 | "source": [
165 | "相比于其他编程语言,Python的一个特色是交互式环境,为我们提供了可以同时编写运行的编程方式。\n",
166 | "\n",
167 | "首先我们下载一个名为 jupyter notebook 的编辑器,它可以支持交互式环境。\n",
168 | "\n",
169 | "在命令行执行命令 `pip install jupyter` 安装编辑器。\n",
170 | "\n",
171 | "然后执行命令 `jupyter notebook`。\n",
172 | "\n",
173 | "这时你发现你的浏览器自动打开了,并且出现了一个在线的精美简洁的编辑器,这就是notebook的主界面。\n",
174 | "\n",
175 | "我们点击右上角的 New 按钮,选择 Python3,然后输入 `print('hello world')`,之后按下上面的 Run 按钮,这时我们发现在代码的下面也出现了hello world。\n"
176 | ]
177 | },
178 | {
179 | "attachments": {},
180 | "cell_type": "markdown",
181 | "id": "fc307911",
182 | "metadata": {},
183 | "source": [
184 | " "
185 | ]
186 | },
187 | {
188 | "attachments": {},
189 | "cell_type": "markdown",
190 | "id": "c999a656",
191 | "metadata": {},
192 | "source": [
193 | "编写代码之后即刻运行,运行之后还可以继续编辑,省去了不停打开编写保存运行的过程,这便是交互式编程的奇妙之处!而交互式编程带来的便捷不止如此,在数据科学中我们经常要处理较大的数据,整个程序的运行动辄十几分钟。通过交互式编程我们可以一行一行运行程序,同时通过下面的输出内容观察程序的中间运行结果,在出现错误时及时修改代码,从而节省重复运行程序的时间!\n",
194 | "\n",
195 | "下面的教程中,交互式编程将全程陪伴你的学习过程,相信随着时间你会更加感触到先进工具带来的效率提升!"
196 | ]
197 | },
198 | {
199 | "attachments": {},
200 | "cell_type": "markdown",
201 | "id": "f738e935",
202 | "metadata": {},
203 | "source": [
204 | "## 1.1.2 Python 常量与变量"
205 | ]
206 | },
207 | {
208 | "attachments": {},
209 | "cell_type": "markdown",
210 | "id": "49d754df",
211 | "metadata": {},
212 | "source": [
213 | "可能你现在会产生疑惑,代码中的 print 代表什么意义?括号又是什么作用?为什么 hello world 外面有个双引号?没关系,下面我们就来了解 Python 语法的奥秘。\n",
214 | "\n",
215 | "首先我们介绍常量与变量,他们相当于语言中的 “名词” 部分,功能是用来表示某些事物。 "
216 | ]
217 | },
218 | {
219 | "attachments": {},
220 | "cell_type": "markdown",
221 | "id": "381ba610",
222 | "metadata": {},
223 | "source": [
224 | "### 1.1.2.1 常量"
225 | ]
226 | },
227 | {
228 | "attachments": {},
229 | "cell_type": "markdown",
230 | "id": "cf0191ed",
231 | "metadata": {},
232 | "source": [
233 | "常量是编程语言中固定的量,它的值不能改变。例如 2 就表示数字二,不能被修改表示其他值。Python 中的常量包括数字,字符串,逻辑值三种。\n",
234 | "\n",
235 | "- 数字:整数(例如2),浮点数(例如2.333 或 1e-9 = $1 * 10^{-9}$)\n",
236 | "- 字符串:用单/双/三引号括起来的内容,例如(\\'Hi\\' 或 \\\"Hi\\\" 或 \\'\\'\\'Hi\\'\\'\\')\n",
237 | "- 逻辑值:True 代表真, False 代表假\n",
238 | "\n",
239 | "使用 `type( * )` 可以查看 \\* 的类型,例如 `type(2)` 返回 int 表示 2 为 整数。"
240 | ]
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": 1,
245 | "id": "685b9615",
246 | "metadata": {},
247 | "outputs": [
248 | {
249 | "data": {
250 | "text/plain": [
251 | "int"
252 | ]
253 | },
254 | "execution_count": 1,
255 | "metadata": {},
256 | "output_type": "execute_result"
257 | }
258 | ],
259 | "source": [
260 | "## 2 表示 整数(integer) 2\n",
261 | "type(2)"
262 | ]
263 | },
264 | {
265 | "cell_type": "code",
266 | "execution_count": 2,
267 | "id": "62aa4541",
268 | "metadata": {},
269 | "outputs": [
270 | {
271 | "data": {
272 | "text/plain": [
273 | "float"
274 | ]
275 | },
276 | "execution_count": 2,
277 | "metadata": {},
278 | "output_type": "execute_result"
279 | }
280 | ],
281 | "source": [
282 | "## 2.333 与 1e-9 表示对应浮点数(float)\n",
283 | "type(2.33)"
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": 3,
289 | "id": "dfa9993d",
290 | "metadata": {},
291 | "outputs": [
292 | {
293 | "data": {
294 | "text/plain": [
295 | "float"
296 | ]
297 | },
298 | "execution_count": 3,
299 | "metadata": {},
300 | "output_type": "execute_result"
301 | }
302 | ],
303 | "source": [
304 | "type(1e-9)"
305 | ]
306 | },
307 | {
308 | "cell_type": "code",
309 | "execution_count": 4,
310 | "id": "1188b441",
311 | "metadata": {},
312 | "outputs": [
313 | {
314 | "data": {
315 | "text/plain": [
316 | "str"
317 | ]
318 | },
319 | "execution_count": 4,
320 | "metadata": {},
321 | "output_type": "execute_result"
322 | }
323 | ],
324 | "source": [
325 | "## 用单引号括起来的内容表示字符串(string)\n",
326 | "\n",
327 | "type('这是1个字符串')"
328 | ]
329 | },
330 | {
331 | "cell_type": "code",
332 | "execution_count": 5,
333 | "id": "31d968df",
334 | "metadata": {},
335 | "outputs": [
336 | {
337 | "data": {
338 | "text/plain": [
339 | "bool"
340 | ]
341 | },
342 | "execution_count": 5,
343 | "metadata": {},
344 | "output_type": "execute_result"
345 | }
346 | ],
347 | "source": [
348 | "## True 代表逻辑值(Boolen)\n",
349 | "type(True)"
350 | ]
351 | },
352 | {
353 | "cell_type": "code",
354 | "execution_count": 6,
355 | "id": "8fb8a11f",
356 | "metadata": {},
357 | "outputs": [
358 | {
359 | "data": {
360 | "text/plain": [
361 | "bool"
362 | ]
363 | },
364 | "execution_count": 6,
365 | "metadata": {},
366 | "output_type": "execute_result"
367 | }
368 | ],
369 | "source": [
370 | "\n",
371 | "type(False)"
372 | ]
373 | },
374 | {
375 | "attachments": {},
376 | "cell_type": "markdown",
377 | "id": "35483a24",
378 | "metadata": {},
379 | "source": [
380 | "### 1.1.2.2 变量"
381 | ]
382 | },
383 | {
384 | "attachments": {},
385 | "cell_type": "markdown",
386 | "id": "fd4b3a41",
387 | "metadata": {},
388 | "source": [
389 | "与常量相反,变量可以存储不同的值以表示不同的内容,并且它的值可以被更改。变量通过赋值符号 `=` 创建,例如 `variable = 1`。\n",
390 | "\n",
391 | "注意变量存在命名规范。变量的第一个字符必须是字母或下划线,其余部分由下划线或数字组成,且区分大小写。例如 `a_123` 可以是一个变量,123_a 不可以是一个变量,`A_123` 与 `a_123` 表示两个不同变量。"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": 7,
397 | "id": "ae73cca9",
398 | "metadata": {},
399 | "outputs": [
400 | {
401 | "data": {
402 | "text/plain": [
403 | "int"
404 | ]
405 | },
406 | "execution_count": 7,
407 | "metadata": {},
408 | "output_type": "execute_result"
409 | }
410 | ],
411 | "source": [
412 | "## 创建名为 variable 的变量存储一个 整数 值\n",
413 | "\n",
414 | "variable = 1\n",
415 | "type(variable)"
416 | ]
417 | },
418 | {
419 | "cell_type": "code",
420 | "execution_count": 8,
421 | "id": "da126551",
422 | "metadata": {},
423 | "outputs": [
424 | {
425 | "data": {
426 | "text/plain": [
427 | "str"
428 | ]
429 | },
430 | "execution_count": 8,
431 | "metadata": {},
432 | "output_type": "execute_result"
433 | }
434 | ],
435 | "source": [
436 | "## 修改 variable 变量的值为一个字符串\n",
437 | "\n",
438 | "variable = 'Hi'\n",
439 | "type(variable)"
440 | ]
441 | },
442 | {
443 | "cell_type": "code",
444 | "execution_count": 9,
445 | "id": "6d88ecf8",
446 | "metadata": {},
447 | "outputs": [
448 | {
449 | "ename": "SyntaxError",
450 | "evalue": "cannot assign to literal (2270411785.py, line 3)",
451 | "output_type": "error",
452 | "traceback": [
453 | "\u001b[0;36m Input \u001b[0;32mIn [9]\u001b[0;36m\u001b[0m\n\u001b[0;31m 2.33 = 2.55\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m cannot assign to literal\n"
454 | ]
455 | }
456 | ],
457 | "source": [
458 | "## 常量的值无法修改 触发语法错误提示\n",
459 | "\n",
460 | "2.33 = 2.55"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": 10,
466 | "id": "f43e2af4",
467 | "metadata": {},
468 | "outputs": [
469 | {
470 | "ename": "SyntaxError",
471 | "evalue": "invalid decimal literal (4228011246.py, line 3)",
472 | "output_type": "error",
473 | "traceback": [
474 | "\u001b[0;36m Input \u001b[0;32mIn [10]\u001b[0;36m\u001b[0m\n\u001b[0;31m 123_a = 1\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid decimal literal\n"
475 | ]
476 | }
477 | ],
478 | "source": [
479 | "## 变量的命名不满足规范 触发语法错误提示\n",
480 | "\n",
481 | "123_a = 1"
482 | ]
483 | },
484 | {
485 | "attachments": {},
486 | "cell_type": "markdown",
487 | "id": "e49db2cb",
488 | "metadata": {},
489 | "source": [
490 | "## 1.1.3 Python 运算符与函数"
491 | ]
492 | },
493 | {
494 | "attachments": {},
495 | "cell_type": "markdown",
496 | "id": "c1d6e269",
497 | "metadata": {},
498 | "source": [
499 | "学习了常量与变量之后,我们可以在 Python 中表示一些数值或字符串,然而要想解决更复杂的问题,我们需要了解如何对这些常量与变量进行操作。\n",
500 | "\n",
501 | "运算符与函数相当于语言中的 “动词” 部分,用来表示某种操作。"
502 | ]
503 | },
504 | {
505 | "attachments": {},
506 | "cell_type": "markdown",
507 | "id": "f19dc5ce",
508 | "metadata": {},
509 | "source": [
510 | "### 1.1.3.1 运算符"
511 | ]
512 | },
513 | {
514 | "attachments": {},
515 | "cell_type": "markdown",
516 | "id": "6b9e4f82",
517 | "metadata": {},
518 | "source": [
519 | "运算符有以下几种,表示运算操作/逻辑操作/位运算操作\n",
520 | "\n",
521 | "- 算数运算符:\n",
522 | " - `+` 表示加法,`1 + 2` 的结果是 3\n",
523 | " - `-` 表示减法,`1 - 2` 的结果是 -1\n",
524 | " - `*` 表示乘法,`1 * 2` 的结果是 2\n",
525 | " - `**` 表示乘方,`1 ** 2` 的结果是 1\n",
526 | " - `/` 表示除法,`1 / 2` 的结果是 0.5 \n",
527 | " - `//` 表示整除,`1 // 2` 的结果是 0 (相当于除法结果向下取整)\n",
528 | " - `%` 表示取余,`1 % 2` 的结果是 1\n",
529 | " \n",
530 | " \n",
531 | "- 逻辑运算符\n",
532 | " - `>` 表示大于,`1 > 2` 的结果是 False\n",
533 | " - `>=` 表示大于等于, `1 >= 2` 的结果是 False\n",
534 | " - `<=` 表示小于,`1 <= 2` 的结果是 True\n",
535 | " - `<` 表示小于等于, `1 < 2` 的结果是 True\n",
536 | " - `==` 表示等于, `1 == 2` 的结果是 False\n",
537 | " - `!=` 表示不等于, `1 != 2` 的结果是 True\n",
538 | " - `and` 表示逻辑\"与\",`True and False` 的结果是 False\n",
539 | " - `or` 表示逻辑\"或\",`True or False` 的结果是 True\n",
540 | " - `not` 表示逻辑\"非\",`not True` 的结果是 False\n",
541 | " \n",
542 | " \n",
543 | "- 位运算符\n",
544 | " - `>>` 表示右移操作\n",
545 | " - `<<` 表示左移操作\n",
546 | " - `&` 表示按位与\n",
547 | " - `|` 表示按位或\n",
548 | " - `^` 表示按位异或\n",
549 | " - `~` 表示按位取反\n",
550 | " \n",
551 | "其中最常用的是算数运算符与逻辑运算符,位运算符在 集合 操作中经常使用。\n",
552 | "\n",
553 | "附:逻辑运算参照表\n",
554 | "\n",
555 | "| X | Y | X and Y | X or Y | not X | not Y |\n",
556 | "| ----- | ----- | ------- | ------ | ----- | ----- |\n",
557 | "| True | True | True | True | False | False |\n",
558 | "| True | False | False | True | False | True |\n",
559 | "| False | False | False | False | True | True |\n",
560 | "| False | True | False | True | True | False |\n"
561 | ]
562 | },
563 | {
564 | "attachments": {},
565 | "cell_type": "markdown",
566 | "id": "4ca325e9",
567 | "metadata": {},
568 | "source": [
569 | "> 问题:给你任意五个整数和一个目标值target,找到这五个整数中和为target的那两个整数。\n",
570 | "\n",
571 | "例如:\n",
572 | "\n",
573 | " 输入:2,3,7,11,15, target = 13\n",
574 | " 输出:2,11\n",
575 | " 解释:第0个数和第3个数的和为13 (注:编程时我们习惯从第0个开始数)"
576 | ]
577 | },
578 | {
579 | "cell_type": "code",
580 | "execution_count": 11,
581 | "id": "2821138d",
582 | "metadata": {},
583 | "outputs": [
584 | {
585 | "data": {
586 | "text/plain": [
587 | "False"
588 | ]
589 | },
590 | "execution_count": 11,
591 | "metadata": {},
592 | "output_type": "execute_result"
593 | }
594 | ],
595 | "source": [
596 | "## 尝试求解,改变 a b 的值依次两两尝试,直到 a + b = target\n",
597 | "\n",
598 | "target = 13\n",
599 | "a = 2\n",
600 | "b = 3\n",
601 | "a + b == target"
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "execution_count": 12,
607 | "id": "d735f2c4",
608 | "metadata": {},
609 | "outputs": [
610 | {
611 | "data": {
612 | "text/plain": [
613 | "False"
614 | ]
615 | },
616 | "execution_count": 12,
617 | "metadata": {},
618 | "output_type": "execute_result"
619 | }
620 | ],
621 | "source": [
622 | "a = 2\n",
623 | "b = 7\n",
624 | "a + b == target"
625 | ]
626 | },
627 | {
628 | "cell_type": "code",
629 | "execution_count": 13,
630 | "id": "6d18a586",
631 | "metadata": {},
632 | "outputs": [
633 | {
634 | "data": {
635 | "text/plain": [
636 | "True"
637 | ]
638 | },
639 | "execution_count": 13,
640 | "metadata": {},
641 | "output_type": "execute_result"
642 | }
643 | ],
644 | "source": [
645 | "a = 2\n",
646 | "b = 11\n",
647 | "a + b == target"
648 | ]
649 | },
650 | {
651 | "cell_type": "code",
652 | "execution_count": 14,
653 | "id": "0e477e9a",
654 | "metadata": {},
655 | "outputs": [
656 | {
657 | "data": {
658 | "text/plain": [
659 | "(2, 11)"
660 | ]
661 | },
662 | "execution_count": 14,
663 | "metadata": {},
664 | "output_type": "execute_result"
665 | }
666 | ],
667 | "source": [
668 | "a,b"
669 | ]
670 | },
671 | {
672 | "attachments": {},
673 | "cell_type": "markdown",
674 | "id": "6398ea1d",
675 | "metadata": {},
676 | "source": [
677 | "### 1.1.3.2 函数"
678 | ]
679 | },
680 | {
681 | "attachments": {},
682 | "cell_type": "markdown",
683 | "id": "fd415b9c",
684 | "metadata": {},
685 | "source": [
686 | "在上述过程中,下列代码被重复多次书写,这时我们可以使用函数减少代码冗余。函数是一种可复用的部件,用于定义更加复杂的操作以减少代码冗余。\n",
687 | "\n",
688 | " a = *\n",
689 | " b = *\n",
690 | " a + b == target\n",
691 | " \n",
692 | "如果把运算符比作 “握” “抬手” “张嘴” “吞咽” 等基本动作,那么函数往往是 “吃饭” “喝水” 等一系列基本动作构成的复杂动作。"
693 | ]
694 | },
695 | {
696 | "attachments": {},
697 | "cell_type": "markdown",
698 | "id": "fed1bec7",
699 | "metadata": {},
700 | "source": [
701 | "函数通过 `def` 关键字定义,函数的输入由函数名后括号内 参数 定义,函数的结果由 `return` 关键字定义。\n",
702 | "\n",
703 | "- 函数的 参数 由逗号分隔,在定义函数时的参数叫做形参,在使用函数时输入的参数叫做实参。\n",
704 | "- 函数的 返回值 是函数的返回结果,参数与返回值都是可选的。\n",
705 | "\n",
706 | "另外程序中还存在着预先定义好的函数,例如我们在前面使用的 `type` 函数。以及 1.1.1.3 节中使用的 `print` 函数,它的功能是在屏幕输出某个变量的内容。可能你早就心存疑惑,为什么上面不用 `print` 也能输出呢?原因就在于交互式环境 notebook 会自动输出最后一个变量的内容。"
707 | ]
708 | },
709 | {
710 | "cell_type": "code",
711 | "execution_count": 15,
712 | "id": "58f76199",
713 | "metadata": {},
714 | "outputs": [
715 | {
716 | "data": {
717 | "text/plain": [
718 | "13"
719 | ]
720 | },
721 | "execution_count": 15,
722 | "metadata": {},
723 | "output_type": "execute_result"
724 | }
725 | ],
726 | "source": [
727 | "## 自动输出最后的 target\n",
728 | "\n",
729 | "variable\n",
730 | "target"
731 | ]
732 | },
733 | {
734 | "cell_type": "code",
735 | "execution_count": 16,
736 | "id": "2e70c894",
737 | "metadata": {},
738 | "outputs": [
739 | {
740 | "data": {
741 | "text/plain": [
742 | "'Hi'"
743 | ]
744 | },
745 | "execution_count": 16,
746 | "metadata": {},
747 | "output_type": "execute_result"
748 | }
749 | ],
750 | "source": [
751 | "## 自动输出最后的 variable\n",
752 | "\n",
753 | "target\n",
754 | "variable"
755 | ]
756 | },
757 | {
758 | "attachments": {},
759 | "cell_type": "markdown",
760 | "id": "e1e4e4b2",
761 | "metadata": {},
762 | "source": [
763 | "下面我们尝试定义一个函数减少之前代码的冗余。"
764 | ]
765 | },
766 | {
767 | "cell_type": "code",
768 | "execution_count": 17,
769 | "id": "7c3f5f65",
770 | "metadata": {},
771 | "outputs": [],
772 | "source": [
773 | "## num1,num2 是输入的参数, return 后面的 a+b==target 是函数的结果\n",
774 | "\n",
775 | "## 这里num1,num2,target 是形参\n",
776 | "def check_sum(num1, num2, target):\n",
777 | " ## 在 def xxx(): 下面缩进的是函数的内容\n",
778 | " a = num1\n",
779 | " b = num2\n",
780 | " return a + b == target"
781 | ]
782 | },
783 | {
784 | "attachments": {},
785 | "cell_type": "markdown",
786 | "id": "b7caf8c4",
787 | "metadata": {},
788 | "source": [
789 | "Python的一大语法特点是缩进敏感,这里第 5,6,7 行距离开头有 1个TAB / 4个空格 的距离并不只是为了美观,而是为了说明第 5,6,7 行是函数的内容。相比下面 C++ 函数用花括号的表示方法,相信你可以在这个角度感受 Python 的简洁。 \n",
790 | "\n",
791 | " int check_sum(int num1, int num2, int target)\n",
792 | " {\n",
793 | " int a = num1;\n",
794 | " int b = num2;\n",
795 | " return a + b == target;\n",
796 | " }\n",
797 | " \n",
798 | "下面我们尝试调用前面定义的 check_sum 函数完成之前的任务。"
799 | ]
800 | },
801 | {
802 | "cell_type": "code",
803 | "execution_count": 18,
804 | "id": "5a5c2851",
805 | "metadata": {},
806 | "outputs": [
807 | {
808 | "name": "stdout",
809 | "output_type": "stream",
810 | "text": [
811 | "False\n",
812 | "False\n",
813 | "True\n"
814 | ]
815 | }
816 | ],
817 | "source": [
818 | "## 这里 2,3,13 是实参,函数返回结果 False\n",
819 | "\n",
820 | "print(check_sum(2, 3, 13))\n",
821 | "\n",
822 | "print(check_sum(2, 7, 13))\n",
823 | "\n",
824 | "print(check_sum(2, 11, 13))"
825 | ]
826 | },
827 | {
828 | "attachments": {},
829 | "cell_type": "markdown",
830 | "id": "7a0d0603",
831 | "metadata": {},
832 | "source": [
833 | "通过引入函数,上面的小例子变得更加简洁。然而我们发现无论测试哪两个数字的和与target一致,target的值是始终不变的。我们可以通过引入 局部变量 与 全局变量 简化函数。\n",
834 | "\n",
835 | "- 局部变量:只在函数内部生效的变量,在函数外部无法使用。\n",
836 | "- 全局变量:在整个代码中都生效的变量,在函数内/外部都可使用。\n",
837 | "\n",
838 | "在 `check_sum` 中定义的变量 `a`, `b`, `num1`, `num2`, `target` 都属于局部变量。\n",
839 | "\n",
840 | "在 1.1.3.1 节中我们定义的 `target` 变量属于全局变量。当我们希望在函数内部使用全局变量时,应当用 `global` 关键字予以标注。"
841 | ]
842 | },
843 | {
844 | "cell_type": "code",
845 | "execution_count": 19,
846 | "id": "021a6351",
847 | "metadata": {},
848 | "outputs": [
849 | {
850 | "ename": "NameError",
851 | "evalue": "name 'num1' is not defined",
852 | "output_type": "error",
853 | "traceback": [
854 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
855 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
856 | "\u001b[1;32m/Users/chuanyu/Code/learn-python-the-smart-way/1. Python 安装及基本语法.ipynb Cell 54'\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1 \u001b[0m \u001b[39m## 尝试在函数外部使用变量 num1,系统报错 num1 未定义\u001b[39;00m\n\u001b[0;32m----> 3 \u001b[0m \u001b[39mprint\u001b[39m(num1)\n",
857 | "\u001b[0;31mNameError\u001b[0m: name 'num1' is not defined"
858 | ]
859 | }
860 | ],
861 | "source": [
862 | "## 尝试在函数外部使用变量 num1,系统报错 num1 未定义\n",
863 | "\n",
864 | "print(num1)"
865 | ]
866 | },
867 | {
868 | "cell_type": "code",
869 | "execution_count": 20,
870 | "id": "b9333b51",
871 | "metadata": {},
872 | "outputs": [],
873 | "source": [
874 | "## 尝试重新定义函数 check_sum, 此时函数参数中已不存在target\n",
875 | "\n",
876 | "def check_sum(num1, num2):\n",
877 | " global target\n",
878 | " a = num1\n",
879 | " b = num2\n",
880 | " return a + b == target"
881 | ]
882 | },
883 | {
884 | "cell_type": "code",
885 | "execution_count": 21,
886 | "id": "bdff7aaa",
887 | "metadata": {},
888 | "outputs": [
889 | {
890 | "name": "stdout",
891 | "output_type": "stream",
892 | "text": [
893 | "False\n",
894 | "False\n",
895 | "True\n"
896 | ]
897 | }
898 | ],
899 | "source": [
900 | "print(check_sum(2, 3))\n",
901 | "\n",
902 | "print(check_sum(2, 7))\n",
903 | "\n",
904 | "print(check_sum(2, 11))"
905 | ]
906 | },
907 | {
908 | "attachments": {},
909 | "cell_type": "markdown",
910 | "id": "a91f7105",
911 | "metadata": {},
912 | "source": [
913 | "通过 全局变量 的方法,我们的函数变得更加简洁了。"
914 | ]
915 | },
916 | {
917 | "attachments": {},
918 | "cell_type": "markdown",
919 | "id": "79c45b74",
920 | "metadata": {},
921 | "source": [
922 | "## 1.1.4 Python 控制流"
923 | ]
924 | },
925 | {
926 | "attachments": {},
927 | "cell_type": "markdown",
928 | "id": "a60fdced",
929 | "metadata": {},
930 | "source": [
931 | "通过运算符与函数,我们可以操作变量完成简单的任务。然而本质上我们还在把 Python 当作一个计算器使用,而不是一个可以实现自动化的编程语言,每行代码按照自上而下的顺序依次执行。通过控制流,我们可以让程序自动判断逻辑,自动跳转到某个位置,从而实现自动控制。\n",
932 | "\n",
933 | "控制流中涉及几个关键字:\n",
934 | "\n",
935 | "- `if-else` 逻辑语句:判断某个条件是否成立,若成立则执行 if 语句,若不成立则执行 else 语句。\n",
936 | "- `while` 循环语句:根据某一条件重复执行某个语句块。\n",
937 | "- `for-in` 循环语句:根据某一序列进行循环迭代,直到迭代完整个序列。(序列这一概念在下章介绍)\n",
938 | "- `break` 停止语句:停止当前 while 或 for-in 循环。\n",
939 | "- `continue` 继续语句:暂停当前 while 或 for-in 循环,继续执行循环到下一个迭代。\n",
940 | "\n",
941 | "控制流就像语言中的“介词”,帮助我们联接名词与动词组成流畅优美的句子。"
942 | ]
943 | },
944 | {
945 | "attachments": {},
946 | "cell_type": "markdown",
947 | "id": "217e80bb",
948 | "metadata": {},
949 | "source": [
950 | "### 1.1.4.1 while 循环语句\n",
951 | "\n",
952 | "while 循环语句根据某一条件重复执行某个语句块,它的基本结构如下:\n",
953 | "\n",
954 | " while ***:\n",
955 | " statement\n",
956 | "\n",
957 | "若 \\*\\*\\* 的结果为 True 则继续重复执行 statement,若结果为 False 则停止循环。"
958 | ]
959 | },
960 | {
961 | "cell_type": "code",
962 | "execution_count": 22,
963 | "id": "cfe76091",
964 | "metadata": {},
965 | "outputs": [
966 | {
967 | "name": "stdout",
968 | "output_type": "stream",
969 | "text": [
970 | "1\n",
971 | "2\n",
972 | "3\n",
973 | "4\n",
974 | "5\n"
975 | ]
976 | }
977 | ],
978 | "source": [
979 | "## while 循环语句样例\n",
980 | "\n",
981 | "a = 0\n",
982 | "while a < 5:\n",
983 | " a = a + 1\n",
984 | " print(a)"
985 | ]
986 | },
987 | {
988 | "attachments": {},
989 | "cell_type": "markdown",
990 | "id": "2f69d818",
991 | "metadata": {},
992 | "source": [
993 | "在上面的代码中,首先我们定义变量 a 的值为 0,之后每次迭代使 a 的值增加 1,并输出当前 a 的值。\n",
994 | "\n",
995 | "当 a 的值等于 5 时,循环停止。"
996 | ]
997 | },
998 | {
999 | "attachments": {},
1000 | "cell_type": "markdown",
1001 | "id": "14a678af",
1002 | "metadata": {},
1003 | "source": [
1004 | "### 1.1.4.2 for 循环语句\n",
1005 | "\n",
1006 | "for-in 据某一序列进行循环迭代,直到迭代完整个序列。\n",
1007 | "\n",
1008 | "首先我们简单介绍下序列,序列只是一个有序的项的集合。例如方括号括起来的一组常量或变量 `[0, 1, 2, 3, 4]` 可以是一个序列。\n",
1009 | "\n",
1010 | "循环的基本结构如下:\n",
1011 | "\n",
1012 | " for * in ***:\n",
1013 | " statement\n",
1014 | "\n",
1015 | "其中 \\*\\*\\* 是被迭代的序列,\\* 是存储当前迭代元素的变量,当 \\*\\*\\* 中所有元素都被迭代一次后,循环停止。\n",
1016 | "\n",
1017 | "在下面的代码中,每次循环迭代序列中的一个元素,直到最后一个元素 5 被迭代。"
1018 | ]
1019 | },
1020 | {
1021 | "cell_type": "code",
1022 | "execution_count": 23,
1023 | "id": "744fb4f9",
1024 | "metadata": {},
1025 | "outputs": [
1026 | {
1027 | "name": "stdout",
1028 | "output_type": "stream",
1029 | "text": [
1030 | "1\n",
1031 | "2\n",
1032 | "3\n",
1033 | "4\n",
1034 | "5\n"
1035 | ]
1036 | }
1037 | ],
1038 | "source": [
1039 | "## for-in 循环语句样例\n",
1040 | "\n",
1041 | "for i in [1,2,3,4,5]:\n",
1042 | " print(i)"
1043 | ]
1044 | },
1045 | {
1046 | "attachments": {},
1047 | "cell_type": "markdown",
1048 | "id": "fa4b05e5",
1049 | "metadata": {},
1050 | "source": [
1051 | "考虑之前的求和问题,在最坏的情况下,我们需要把所有元素两两求和才能得到答案。在5个元素时,我们最多需要对比10次,也就是重复写10次 check_sum 函数。但在有100个元素时,我们需要重复写4950次!因此这时我们用循环进行简化:"
1052 | ]
1053 | },
1054 | {
1055 | "cell_type": "code",
1056 | "execution_count": 24,
1057 | "id": "0511b2de",
1058 | "metadata": {},
1059 | "outputs": [
1060 | {
1061 | "name": "stdout",
1062 | "output_type": "stream",
1063 | "text": [
1064 | "2 2 False\n",
1065 | "2 3 False\n",
1066 | "2 7 False\n",
1067 | "2 11 True\n",
1068 | "2 15 False\n",
1069 | "3 2 False\n",
1070 | "3 3 False\n",
1071 | "3 7 False\n",
1072 | "3 11 False\n",
1073 | "3 15 False\n",
1074 | "7 2 False\n",
1075 | "7 3 False\n",
1076 | "7 7 False\n",
1077 | "7 11 False\n",
1078 | "7 15 False\n",
1079 | "11 2 True\n",
1080 | "11 3 False\n",
1081 | "11 7 False\n",
1082 | "11 11 False\n",
1083 | "11 15 False\n",
1084 | "15 2 False\n",
1085 | "15 3 False\n",
1086 | "15 7 False\n",
1087 | "15 11 False\n",
1088 | "15 15 False\n"
1089 | ]
1090 | }
1091 | ],
1092 | "source": [
1093 | "## 依次迭代元素 a,一共迭代 5 次\n",
1094 | "for a in [2,3,7,11,15]:\n",
1095 | " ## 依次迭代元素 b,一共迭代 5 次\n",
1096 | " for b in [2,3,7,11,15]:\n",
1097 | " ## 每个元素 a 与 5 个元素 b 依次两两尝试,一共迭代了 5 * 5 = 25 次\n",
1098 | " print(a, b, check_sum(a, b))"
1099 | ]
1100 | },
1101 | {
1102 | "attachments": {},
1103 | "cell_type": "markdown",
1104 | "id": "e5ab42e9",
1105 | "metadata": {},
1106 | "source": [
1107 | "在这个例子中,我们可以看到循环是可以嵌套的,在循环的每一次迭代中开启一个新的循环。外层的 `for a in [2, 3, 7, 11, 15]` 按照顺序选择第 1 个元素,内层的 `for b in [2, 3, 7, 11, 15]` 按照顺序选择第 2 个元素,每次迭代输出两个值以及是否与 target 相等。\n",
1108 | "\n",
1109 | "最终我们找到输出 True 的两个元素 ( 2, 11 ),只要三行代码就可以解决问题!"
1110 | ]
1111 | },
1112 | {
1113 | "attachments": {},
1114 | "cell_type": "markdown",
1115 | "id": "0e643a79",
1116 | "metadata": {},
1117 | "source": [
1118 | "### 1.1.4.3 if-else 逻辑语句\n",
1119 | "\n",
1120 | "if else 逻辑语句根据某一条件运行不同代码,它的基本结构如下:\n",
1121 | "\n",
1122 | " if ***:\n",
1123 | " statement1\n",
1124 | " else:\n",
1125 | " statement2\n",
1126 | "\n",
1127 | "若 \\*\\*\\* 的结果为 True 则执行 statement1,若结果为 False 则执行 statement2"
1128 | ]
1129 | },
1130 | {
1131 | "attachments": {},
1132 | "cell_type": "markdown",
1133 | "id": "5492c679",
1134 | "metadata": {},
1135 | "source": [
1136 | "> 女朋友说,下班回来带一个西瓜。如果看到番茄,就买两个。最后程序员买回来两个西瓜。"
1137 | ]
1138 | },
1139 | {
1140 | "attachments": {},
1141 | "cell_type": "markdown",
1142 | "id": "4d539bb4",
1143 | "metadata": {},
1144 | "source": [
1145 | "虽然通过 for-in 不需要写很长代码,然而我们还需要从输出结果中一个个找。通过 if-else 逻辑语句,我们可以让程序真正的实现自动化!\n",
1146 | "\n",
1147 | "这里 pass 代表不进行任何操作。"
1148 | ]
1149 | },
1150 | {
1151 | "cell_type": "code",
1152 | "execution_count": 25,
1153 | "id": "25812afe",
1154 | "metadata": {},
1155 | "outputs": [
1156 | {
1157 | "name": "stdout",
1158 | "output_type": "stream",
1159 | "text": [
1160 | "2 11\n",
1161 | "11 2\n"
1162 | ]
1163 | }
1164 | ],
1165 | "source": [
1166 | "## 加入 if-else 逻辑语句\n",
1167 | "\n",
1168 | "for a in [2,3,7,11,15]:\n",
1169 | " for b in [2,3,7,11,15]:\n",
1170 | " ## 如果 check_sum(a,b)的结果为 True 则 输出,否则什么也不做\n",
1171 | " if check_sum(a,b):\n",
1172 | " print(a, b)\n",
1173 | " else:\n",
1174 | " pass"
1175 | ]
1176 | },
1177 | {
1178 | "attachments": {},
1179 | "cell_type": "markdown",
1180 | "id": "72ef95bd",
1181 | "metadata": {},
1182 | "source": [
1183 | "通过 if-else 逻辑语句,我们仅输出求和等于 target 的两个元素,不再需要从输出结果中逐个查找。"
1184 | ]
1185 | },
1186 | {
1187 | "attachments": {},
1188 | "cell_type": "markdown",
1189 | "id": "31e9a100",
1190 | "metadata": {},
1191 | "source": [
1192 | "### 1.1.4.4 break 停止语句"
1193 | ]
1194 | },
1195 | {
1196 | "attachments": {},
1197 | "cell_type": "markdown",
1198 | "id": "d0f9c702",
1199 | "metadata": {},
1200 | "source": [
1201 | "break 停止语句用于停止当前的循环。在上面的例子中,我们仅输出 1 种顺序即可,可以添加 break 停止语句在找到符合条件的两个元素后停止。\n",
1202 | "\n",
1203 | "注意 break 仅能跳出当前循环,因此我们需要添加一个 finded 变量记录是否已找到符合条件的两个元素,若找到后外层循环也使用 break 跳出。"
1204 | ]
1205 | },
1206 | {
1207 | "cell_type": "code",
1208 | "execution_count": 26,
1209 | "id": "56a56ccc",
1210 | "metadata": {},
1211 | "outputs": [
1212 | {
1213 | "name": "stdout",
1214 | "output_type": "stream",
1215 | "text": [
1216 | "2 11\n"
1217 | ]
1218 | }
1219 | ],
1220 | "source": [
1221 | "## 添加 break 停止语句\n",
1222 | "\n",
1223 | "## finded 初始为 False\n",
1224 | "finded = False\n",
1225 | "for a in [2,3,7,11,15]:\n",
1226 | " for b in [2,3,7,11,15]:\n",
1227 | " if check_sum(a,b):\n",
1228 | " print(a, b)\n",
1229 | " ## 若找到则 finded 变为 True\n",
1230 | " finded = True\n",
1231 | " break\n",
1232 | " else:\n",
1233 | " pass\n",
1234 | " ## 若 finded 为 True,停止外层循环\n",
1235 | " if finded:\n",
1236 | " break"
1237 | ]
1238 | },
1239 | {
1240 | "attachments": {},
1241 | "cell_type": "markdown",
1242 | "id": "c732b477",
1243 | "metadata": {},
1244 | "source": [
1245 | "### 1.1.4.5 continue 继续语句"
1246 | ]
1247 | },
1248 | {
1249 | "attachments": {},
1250 | "cell_type": "markdown",
1251 | "id": "a39a47d1",
1252 | "metadata": {},
1253 | "source": [
1254 | "continue 语句用于停止当前循环并继续执行循环到下一个迭代,下面我们用一个例子展示 continue 的用法。"
1255 | ]
1256 | },
1257 | {
1258 | "cell_type": "code",
1259 | "execution_count": 27,
1260 | "id": "6c93c544",
1261 | "metadata": {},
1262 | "outputs": [
1263 | {
1264 | "name": "stdout",
1265 | "output_type": "stream",
1266 | "text": [
1267 | "2\n",
1268 | "3\n",
1269 | "7\n",
1270 | "11\n",
1271 | "15\n"
1272 | ]
1273 | }
1274 | ],
1275 | "source": [
1276 | "for a in [2,3,7,11,15]:\n",
1277 | " print(a)\n",
1278 | " continue\n",
1279 | " ## continue 使循环停止,并继续执行下一个迭代,后面的内容被跳过\n",
1280 | " print(a + 1)"
1281 | ]
1282 | },
1283 | {
1284 | "attachments": {},
1285 | "cell_type": "markdown",
1286 | "id": "49f3381b",
1287 | "metadata": {},
1288 | "source": [
1289 | "## 1.1.5 练习"
1290 | ]
1291 | },
1292 | {
1293 | "attachments": {},
1294 | "cell_type": "markdown",
1295 | "id": "7d40b4b2",
1296 | "metadata": {},
1297 | "source": [
1298 | "### 1.1.5.1 练习一"
1299 | ]
1300 | },
1301 | {
1302 | "attachments": {},
1303 | "cell_type": "markdown",
1304 | "id": "dd204ed4",
1305 | "metadata": {},
1306 | "source": [
1307 | "> 按规定,某种电子元件使用寿命超过 1000 小时为一级品。已知某一大批产品的一级品率为 0.2,现在从中随机地抽查 20 只。使用 Python 计算 20 只元件中恰好有 k 只 (k=0,1,...,20) 为一级品的概率为?"
1308 | ]
1309 | },
1310 | {
1311 | "attachments": {},
1312 | "cell_type": "markdown",
1313 | "id": "63a98fcd",
1314 | "metadata": {},
1315 | "source": [
1316 | "根据二项分布公式,所求的概率为:\n",
1317 | "\n",
1318 | "$$P\\{X=k\\}=\\left(\\begin{array}{c}\n",
1319 | "20 \\\\\n",
1320 | "k\n",
1321 | "\\end{array}\\right)(0.2)^{k}(0.8)^{20-k}, k=0,1, \\cdots, 20$$"
1322 | ]
1323 | },
1324 | {
1325 | "cell_type": "code",
1326 | "execution_count": 28,
1327 | "id": "ba81f4e4",
1328 | "metadata": {},
1329 | "outputs": [],
1330 | "source": [
1331 | "## 定义阶乘函数,用于排列组合中\n",
1332 | "def multiple(x):\n",
1333 | " result = 1\n",
1334 | " while x != 0:\n",
1335 | " result = result * x\n",
1336 | " x = x - 1\n",
1337 | " return result"
1338 | ]
1339 | },
1340 | {
1341 | "cell_type": "code",
1342 | "execution_count": 29,
1343 | "id": "d2e65330",
1344 | "metadata": {},
1345 | "outputs": [],
1346 | "source": [
1347 | "## 定义二项分布计算函数\n",
1348 | "def p_xk(k):\n",
1349 | " ## 计算排列组合\n",
1350 | " temp = multiple(20) / (multiple(k) * multiple(20 - k))\n",
1351 | " ## 计算概率\n",
1352 | " p = (0.2 ** k) * (0.8 ** (20 - k))\n",
1353 | " return temp * p"
1354 | ]
1355 | },
1356 | {
1357 | "cell_type": "code",
1358 | "execution_count": 30,
1359 | "id": "66c451c4",
1360 | "metadata": {},
1361 | "outputs": [
1362 | {
1363 | "name": "stdout",
1364 | "output_type": "stream",
1365 | "text": [
1366 | "P{ X = 0 } = 0.011529215046068483\n",
1367 | "P{ X = 1 } = 0.05764607523034242\n",
1368 | "P{ X = 2 } = 0.13690942867206327\n",
1369 | "P{ X = 3 } = 0.20536414300809488\n",
1370 | "P{ X = 4 } = 0.21819940194610074\n",
1371 | "P{ X = 5 } = 0.17455952155688062\n",
1372 | "P{ X = 6 } = 0.10909970097305038\n",
1373 | "P{ X = 7 } = 0.054549850486525185\n",
1374 | "P{ X = 8 } = 0.022160876760150862\n",
1375 | "P{ X = 9 } = 0.007386958920050286\n",
1376 | "P{ X = 10 } = 0.0020314137030138287\n",
1377 | "P{ X = 11 } = 0.00046168493250314287\n",
1378 | "P{ X = 12 } = 8.65659248443393e-05\n",
1379 | "P{ X = 13 } = 1.3317834591436813e-05\n",
1380 | "P{ X = 14 } = 1.6647293239296018e-06\n",
1381 | "P{ X = 15 } = 1.6647293239296019e-07\n",
1382 | "P{ X = 16 } = 1.3005697843200012e-08\n",
1383 | "P{ X = 17 } = 7.65041049600001e-10\n",
1384 | "P{ X = 18 } = 3.1876710400000044e-11\n",
1385 | "P{ X = 19 } = 8.38860800000001e-13\n",
1386 | "P{ X = 20 } = 1.0485760000000012e-14\n"
1387 | ]
1388 | }
1389 | ],
1390 | "source": [
1391 | "## 根据二项分布计算概率\n",
1392 | "k = 0\n",
1393 | "while k != 21:\n",
1394 | " print('P{ X =',k,'} = ', p_xk(k))\n",
1395 | " k = k + 1"
1396 | ]
1397 | }
1398 | ],
1399 | "metadata": {
1400 | "kernelspec": {
1401 | "display_name": "Python 3.9.7 ('base')",
1402 | "language": "python",
1403 | "name": "python3"
1404 | },
1405 | "language_info": {
1406 | "codemirror_mode": {
1407 | "name": "ipython",
1408 | "version": 3
1409 | },
1410 | "file_extension": ".py",
1411 | "mimetype": "text/x-python",
1412 | "name": "python",
1413 | "nbconvert_exporter": "python",
1414 | "pygments_lexer": "ipython3",
1415 | "version": "3.9.7"
1416 | },
1417 | "toc": {
1418 | "base_numbering": 1,
1419 | "nav_menu": {},
1420 | "number_sections": false,
1421 | "sideBar": true,
1422 | "skip_h1_title": true,
1423 | "title_cell": "Table of Contents",
1424 | "title_sidebar": "Contents",
1425 | "toc_cell": false,
1426 | "toc_position": {},
1427 | "toc_section_display": true,
1428 | "toc_window_display": true
1429 | },
1430 | "vscode": {
1431 | "interpreter": {
1432 | "hash": "c6e4e9f98eb68ad3b7c296f83d20e6de614cb42e90992a65aa266555a3137d0d"
1433 | }
1434 | }
1435 | },
1436 | "nbformat": 4,
1437 | "nbformat_minor": 5
1438 | }
1439 |
--------------------------------------------------------------------------------
/2. Python 数据结构.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "broadband-zealand",
6 | "metadata": {},
7 | "source": [
8 | "# Python 数据结构"
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "id": "adjustable-newsletter",
14 | "metadata": {},
15 | "source": [
16 | "顾名思义,数据结构是能够将数据组合在一起的一种结构。\n",
17 | "\n",
18 | "在数据科学领域,很多情况下需要将数据进行有序排列。例如我们统计了大学某班 50 人的数学成绩,那么创建 50 个变量例如 XiaoMing = 99, XiaoHu = 86 .... 无疑是非常繁琐的。这时我们可以通过数据结构整合这些数据,例如在上一节中以方括号标识的列表 `[ 99, 86, 77 .... ]`,这将会使我们的程序大大简化。\n",
19 | "\n",
20 | "Python 中常用的数据结构有:\n",
21 | "\n",
22 | "- 列表 List: 用于保存有序项集合的变量,以方括号标识。\n",
23 | "- 元组 Tuple: 用于保存有序项集合的常量,以圆括号标识。\n",
24 | "- 字典 Dict: 用于保存无序(键,值)项集合的变量,以花括号标识。\n",
25 | "- 集合 Set: 用于保存无序项集合的变量,以花括号标识。\n",
26 | "\n",
27 | "瑞士计算机科学家 Niklaus Wirth 曾说过 \"程序 = 数据结构 + 算法\",这个公式在 40 年后的今天仍然成立。掌握 Python 中常用的数据结构是我们设计程序的一大基石。"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "id": "obvious-strength",
33 | "metadata": {},
34 | "source": [
35 | "> 在本节中我们将尝试设计一个学生成绩管理系统,实现对学生成绩的增、删、查、改功能。"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "id": "according-admission",
41 | "metadata": {},
42 | "source": [
43 | "## 1.2.1 列表"
44 | ]
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "id": "union-medication",
49 | "metadata": {},
50 | "source": [
51 | "列表是用于保存有序项集合的变量,通过方括号创建。列表是最容易理解的数据结构,它就像一个任务清单,任务清单的每一项都是一个单独的任务。\n",
52 | "\n",
53 | "下面我们创建一个含有四个整数的列表。"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 1,
59 | "id": "entertaining-setting",
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "l = [1, 2, 3, 4]"
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "id": "through-reconstruction",
69 | "metadata": {},
70 | "source": [
71 | "\n",
72 | "列表支持以下操作:\n",
73 | "\n",
74 | "- 增:通过函数 `append` 可以向列表内增加元素\n",
75 | "- 删:通过关键字 `del` 可以删除列表内元素\n",
76 | "- 查:通过关键字 `[ ]` 可以查找列表某个位置元素\n",
77 | "- 改:通过赋值符号 `=` 可以修改某个位置的元素\n",
78 | "\n",
79 | "列表的优点是:\n",
80 | "\n",
81 | "- 快速向尾部添加元素\n",
82 | "- 快速遍历所有元素\n",
83 | "- 节省占用计算机内容空间"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "id": "expired-chase",
89 | "metadata": {},
90 | "source": [
91 | "### 1.2.1.1 查找元素"
92 | ]
93 | },
94 | {
95 | "cell_type": "markdown",
96 | "id": "stretch-newsletter",
97 | "metadata": {},
98 | "source": [
99 | "我们通过 `[ ]` 关键字查找列表中某个位置的元素。\n",
100 | "\n",
101 | "例如 `l[0]` 可以获取列表中首个元素,`l[1]` 可以获取列表中第 2 个元素。同时它还支持倒序查找,例如 `l[-1]` 表示倒数第一个元素(末尾的元素)。"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "execution_count": 2,
107 | "id": "covered-douglas",
108 | "metadata": {},
109 | "outputs": [
110 | {
111 | "name": "stdout",
112 | "output_type": "stream",
113 | "text": [
114 | "1\n",
115 | "2\n",
116 | "4\n",
117 | "3\n"
118 | ]
119 | }
120 | ],
121 | "source": [
122 | "## 查找 首个 元素\n",
123 | "print(l[0])\n",
124 | "## 查找第 2 个元素\n",
125 | "print(l[1])\n",
126 | "## 查找第 最后 元素\n",
127 | "print(l[-1])\n",
128 | "## 查找倒数第 2 个元素\n",
129 | "print(l[-2])"
130 | ]
131 | },
132 | {
133 | "cell_type": "markdown",
134 | "id": "photographic-worker",
135 | "metadata": {},
136 | "source": [
137 | "`[ ]` 关键字也可以通过 “切片” 的形式获取含有多个元素的子列表。\n",
138 | "\n",
139 | "例如 `l[0:2]` 代表列表从中第 0 个元素 到 第 2 个元素(左闭右开 `[ ) `,不包括第 2 个元素)"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": 3,
145 | "id": "informative-national",
146 | "metadata": {},
147 | "outputs": [
148 | {
149 | "name": "stdout",
150 | "output_type": "stream",
151 | "text": [
152 | "[1, 2]\n",
153 | "[2, 3]\n"
154 | ]
155 | }
156 | ],
157 | "source": [
158 | "## 查找第 0 到 第 2 的元素子列表\n",
159 | "print(l[0:2])\n",
160 | "## 查找第 1 到 最后 的元素子列表\n",
161 | "print(l[1:-1])"
162 | ]
163 | },
164 | {
165 | "cell_type": "markdown",
166 | "id": "bronze-brook",
167 | "metadata": {},
168 | "source": [
169 | "### 1.2.1.2 修改元素"
170 | ]
171 | },
172 | {
173 | "cell_type": "markdown",
174 | "id": "alien-appeal",
175 | "metadata": {},
176 | "source": [
177 | "通过 `[ ]` 关键字同样可以修改列表中某个位置的元素,类似的它也支持倒序以及切片的形式。"
178 | ]
179 | },
180 | {
181 | "cell_type": "code",
182 | "execution_count": 4,
183 | "id": "verbal-writing",
184 | "metadata": {},
185 | "outputs": [
186 | {
187 | "name": "stdout",
188 | "output_type": "stream",
189 | "text": [
190 | "[-1, 2, 3, 4]\n"
191 | ]
192 | }
193 | ],
194 | "source": [
195 | "## 修改 首个 元素的值为 -1\n",
196 | "l[0] = -1\n",
197 | "print(l)"
198 | ]
199 | },
200 | {
201 | "cell_type": "code",
202 | "execution_count": 5,
203 | "id": "eastern-royalty",
204 | "metadata": {},
205 | "outputs": [
206 | {
207 | "name": "stdout",
208 | "output_type": "stream",
209 | "text": [
210 | "[-1, -2, 3, 4]\n"
211 | ]
212 | }
213 | ],
214 | "source": [
215 | "## 修改从第 0 到第 2 的元素子列表的值为 [-1, -2]\n",
216 | "l[0:2] = [-1, -2]\n",
217 | "print(l)"
218 | ]
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "id": "trained-saskatchewan",
223 | "metadata": {},
224 | "source": [
225 | "### 1.2.1.3 增加元素"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "id": "political-astrology",
231 | "metadata": {},
232 | "source": [
233 | "通过 `append` 函数可以实现向列表尾部添加新的元素。"
234 | ]
235 | },
236 | {
237 | "cell_type": "code",
238 | "execution_count": 6,
239 | "id": "unavailable-chosen",
240 | "metadata": {},
241 | "outputs": [
242 | {
243 | "name": "stdout",
244 | "output_type": "stream",
245 | "text": [
246 | "[-1, -2, 3, 4, 5]\n",
247 | "[-1, -2, 3, 4, 5, 6]\n"
248 | ]
249 | }
250 | ],
251 | "source": [
252 | "## 向集合尾部添加元素 5\n",
253 | "l.append(5)\n",
254 | "print(l)\n",
255 | "## 向集合尾部添加元素 6\n",
256 | "l.append(6)\n",
257 | "print(l)"
258 | ]
259 | },
260 | {
261 | "cell_type": "markdown",
262 | "id": "hundred-ability",
263 | "metadata": {},
264 | "source": [
265 | "### 1.2.1.4 删除元素"
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "id": "similar-delhi",
271 | "metadata": {},
272 | "source": [
273 | "通过 `del` 关键字可以删除列表某个位置的元素。"
274 | ]
275 | },
276 | {
277 | "cell_type": "code",
278 | "execution_count": 7,
279 | "id": "female-temple",
280 | "metadata": {},
281 | "outputs": [
282 | {
283 | "name": "stdout",
284 | "output_type": "stream",
285 | "text": [
286 | "[-2, 3, 4, 5, 6]\n",
287 | "[-2, 3, 4, 5]\n"
288 | ]
289 | }
290 | ],
291 | "source": [
292 | "## 删除列表 首个 元素\n",
293 | "del l[0]\n",
294 | "print(l)\n",
295 | "## 删除列表 最后一个 元素\n",
296 | "del l[-1]\n",
297 | "print(l)"
298 | ]
299 | },
300 | {
301 | "cell_type": "markdown",
302 | "id": "better-architect",
303 | "metadata": {},
304 | "source": [
305 | "### 1.2.1.5 小例子"
306 | ]
307 | },
308 | {
309 | "cell_type": "markdown",
310 | "id": "correct-coalition",
311 | "metadata": {},
312 | "source": [
313 | "在熟悉了列表的增删查找功能后,我们就可以尝试以此为基础搭建我们的学生成绩管理系统。"
314 | ]
315 | },
316 | {
317 | "cell_type": "markdown",
318 | "id": "front-consequence",
319 | "metadata": {},
320 | "source": [
321 | "\n",
322 | "\n",
323 | "\n",
324 | "\n",
325 | "Task 1. 在上一次期末考试中,XiaoHu 考了数学 65 分,语文 55 分;XiaoMing 考了数学 80 分,语文92 分;XiaoWei 考了数学 95 分,语文 98 分,以此建立学生成绩管理系统。\n",
326 | "\n",
327 | "Task 2. 在本次期末考试中,XiaoHu 考了数学 95 分,语文 85 分;XiaoMing 考了数学 75 分,语文 71 分;XiaoWei 考了数学 92 分,语文 93 分,以此对之前的成绩进行更新。\n",
328 | "\n",
329 | "Task 3. 由于 XiaoMing 的成绩出现了大幅度下滑,家长决定要 XiaoMing 转学到另一所高中,以此在系统中删除 XiaoMing 的信息。\n",
330 | "\n",
331 | "Task 4. 学校新转来的学生 Cryin 本次考试成绩为 数学 87 分,语文 88 分,在系统中录入 Cryin 的成绩。\n",
332 | "\n",
333 | " "
334 | ]
335 | },
336 | {
337 | "cell_type": "code",
338 | "execution_count": 8,
339 | "id": "powerful-flower",
340 | "metadata": {},
341 | "outputs": [],
342 | "source": [
343 | "## Task 1 建立学生信息管理系统\n",
344 | "\n",
345 | "## 首先建立一个 “名字” 列表记录哪个学生在列表的哪个位置。\n",
346 | "names = ['XiaoHu', 'XiaoMing', 'XiaoWei']\n",
347 | "\n",
348 | "## 根据名字列表的位置分别建立 “语文成绩” “数学成绩列表” 列表。\n",
349 | "Math_scores = [65, 80, 95]\n",
350 | "Chinese_scores = [55, 92, 98]"
351 | ]
352 | },
353 | {
354 | "cell_type": "code",
355 | "execution_count": 9,
356 | "id": "handled-throat",
357 | "metadata": {},
358 | "outputs": [],
359 | "source": [
360 | "## Task 2 根据本次期末考试的成绩更新系统\n",
361 | "\n",
362 | "## 首先找到 \"XiaoHu\" 在哪个位置,更新该位置的成绩\n",
363 | "## 通过 for-in 循环遍历名字元素\n",
364 | "position = None\n",
365 | "count = 0\n",
366 | "for name in names:\n",
367 | " ## 找到 XiaoHu 在列表中的位置\n",
368 | " if name == \"XiaoHu\":\n",
369 | " position = count\n",
370 | " count = count + 1\n",
371 | "## 根据 XiaoHu 在列表中的位置更新成绩\n",
372 | "Math_scores[position] = 95\n",
373 | "Chinese_scores[position] = 85\n",
374 | "\n",
375 | "## 以同样方法更新 XiaoMing 与 XiaoWei 的成绩\n",
376 | "position = None\n",
377 | "count = 0\n",
378 | "for name in names:\n",
379 | " if name == \"XiaoMing\":\n",
380 | " position = count\n",
381 | " count = count + 1\n",
382 | "Math_scores[position] = 75\n",
383 | "Chinese_scores[position] = 71\n",
384 | "\n",
385 | "position = None\n",
386 | "count = 0\n",
387 | "for name in names:\n",
388 | " if name == \"XiaoWei\":\n",
389 | " position = count\n",
390 | " count = count + 1\n",
391 | "Math_scores[position] = 92\n",
392 | "Chinese_scores[position] = 93"
393 | ]
394 | },
395 | {
396 | "cell_type": "code",
397 | "execution_count": 10,
398 | "id": "expensive-assembly",
399 | "metadata": {},
400 | "outputs": [
401 | {
402 | "name": "stdout",
403 | "output_type": "stream",
404 | "text": [
405 | "['XiaoHu', 'XiaoMing', 'XiaoWei']\n",
406 | "[95, 75, 92]\n",
407 | "[85, 71, 93]\n"
408 | ]
409 | }
410 | ],
411 | "source": [
412 | "print(names)\n",
413 | "print(Math_scores)\n",
414 | "print(Chinese_scores)"
415 | ]
416 | },
417 | {
418 | "cell_type": "code",
419 | "execution_count": 11,
420 | "id": "healthy-blood",
421 | "metadata": {},
422 | "outputs": [],
423 | "source": [
424 | "## Task 3 删除 XiaoMing 的信息\n",
425 | "\n",
426 | "## 首先找到 \"XiaoMing\" 在哪个位置\n",
427 | "## 通过 for-in 循环遍历名字元素\n",
428 | "position = None\n",
429 | "count = 0\n",
430 | "for name in names:\n",
431 | " ## 找到 XiaoMing 在列表中的位置\n",
432 | " if name == \"XiaoMing\":\n",
433 | " position = count\n",
434 | " count = count + 1\n",
435 | "## 根据 XiaoMing 在列表中的位置删除\n",
436 | "del names[position]\n",
437 | "del Math_scores[position]\n",
438 | "del Chinese_scores[position]"
439 | ]
440 | },
441 | {
442 | "cell_type": "code",
443 | "execution_count": 12,
444 | "id": "olive-plumbing",
445 | "metadata": {},
446 | "outputs": [
447 | {
448 | "name": "stdout",
449 | "output_type": "stream",
450 | "text": [
451 | "['XiaoHu', 'XiaoWei']\n",
452 | "[95, 92]\n",
453 | "[85, 93]\n"
454 | ]
455 | }
456 | ],
457 | "source": [
458 | "print(names)\n",
459 | "print(Math_scores)\n",
460 | "print(Chinese_scores)"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": 13,
466 | "id": "homeless-bangladesh",
467 | "metadata": {},
468 | "outputs": [],
469 | "source": [
470 | "## Task 4 录入 Cryin 的信息\n",
471 | "\n",
472 | "names.append('Cryin')\n",
473 | "Math_scores.append(87)\n",
474 | "Chinese_scores.append(88)"
475 | ]
476 | },
477 | {
478 | "cell_type": "code",
479 | "execution_count": 14,
480 | "id": "european-encounter",
481 | "metadata": {},
482 | "outputs": [
483 | {
484 | "name": "stdout",
485 | "output_type": "stream",
486 | "text": [
487 | "['XiaoHu', 'XiaoWei', 'Cryin']\n",
488 | "[95, 92, 87]\n",
489 | "[85, 93, 88]\n"
490 | ]
491 | }
492 | ],
493 | "source": [
494 | "print(names)\n",
495 | "print(Math_scores)\n",
496 | "print(Chinese_scores)"
497 | ]
498 | },
499 | {
500 | "cell_type": "markdown",
501 | "id": "confident-utility",
502 | "metadata": {},
503 | "source": [
504 | "以上我们就初步实现了学生成绩管理系统,并实现了用户的一些简单需求。可以发现列表的增删改操作相对轻松,但最困难的部分是需要遍历整个列表寻找元素在列表中的位置,这种困难是由列表在计算机中的存储形式决定的。后面我们介绍的数据结构 “字典” 可以用来解决这个问题。"
505 | ]
506 | },
507 | {
508 | "cell_type": "markdown",
509 | "id": "alien-magnitude",
510 | "metadata": {},
511 | "source": [
512 | "## 1.2.2 元组"
513 | ]
514 | },
515 | {
516 | "cell_type": "markdown",
517 | "id": "composed-sigma",
518 | "metadata": {},
519 | "source": [
520 | "元组与列表具有近乎一样的特性,他们唯一的区别在于元组无法被修改。由于不可修改的特性,元组一般用来保证存放数据的可靠性,例如用元组保存八大行星的名称,因为它们的名称不会被改变,也不会轻易减少: \n",
521 | "\n",
522 | " planets = [ Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune]\n",
523 | "\n",
524 | "下面我们创建一个含有四个元素的元组。"
525 | ]
526 | },
527 | {
528 | "cell_type": "code",
529 | "execution_count": 15,
530 | "id": "welcome-philippines",
531 | "metadata": {},
532 | "outputs": [],
533 | "source": [
534 | "t = (1, 2, 3, 4)"
535 | ]
536 | },
537 | {
538 | "cell_type": "code",
539 | "execution_count": 16,
540 | "id": "vocal-regard",
541 | "metadata": {},
542 | "outputs": [
543 | {
544 | "ename": "TypeError",
545 | "evalue": "'tuple' object does not support item assignment",
546 | "output_type": "error",
547 | "traceback": [
548 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
549 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
550 | "\u001b[1;32m/Users/chuanyu/Code/learn-python-the-smart-way/2. Python 数据结构.ipynb Cell 37'\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1 \u001b[0m \u001b[39m## 尝试修改元组,提示元素无法被赋值\u001b[39;00m\n\u001b[0;32m----> 3 \u001b[0m t[\u001b[39m0\u001b[39m] \u001b[39m=\u001b[39m \u001b[39m-\u001b[39m\u001b[39m1\u001b[39m\n",
551 | "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
552 | ]
553 | }
554 | ],
555 | "source": [
556 | "## 尝试修改元组,提示元素无法被赋值\n",
557 | "\n",
558 | "t[0] = -1"
559 | ]
560 | },
561 | {
562 | "cell_type": "code",
563 | "execution_count": 17,
564 | "id": "friendly-designation",
565 | "metadata": {},
566 | "outputs": [
567 | {
568 | "ename": "AttributeError",
569 | "evalue": "'tuple' object has no attribute 'append'",
570 | "output_type": "error",
571 | "traceback": [
572 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
573 | "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
574 | "\u001b[1;32m/Users/chuanyu/Code/learn-python-the-smart-way/2. Python 数据结构.ipynb Cell 38'\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1 \u001b[0m \u001b[39m## 尝试增加元素,系统提示不支持 append 操作\u001b[39;00m\n\u001b[0;32m----> 2 \u001b[0m t\u001b[39m.\u001b[39;49mappend(\u001b[39m5\u001b[39m)\n",
575 | "\u001b[0;31mAttributeError\u001b[0m: 'tuple' object has no attribute 'append'"
576 | ]
577 | }
578 | ],
579 | "source": [
580 | "## 尝试增加元素,系统提示不支持 append 操作\n",
581 | "t.append(5)"
582 | ]
583 | },
584 | {
585 | "cell_type": "code",
586 | "execution_count": 18,
587 | "id": "acceptable-denver",
588 | "metadata": {},
589 | "outputs": [
590 | {
591 | "ename": "TypeError",
592 | "evalue": "'tuple' object doesn't support item deletion",
593 | "output_type": "error",
594 | "traceback": [
595 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
596 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
597 | "\u001b[1;32m/Users/chuanyu/Code/learn-python-the-smart-way/2. Python 数据结构.ipynb Cell 39'\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1 \u001b[0m \u001b[39m## 尝试删除元素,系统提示元素无法被删除\u001b[39;00m\n\u001b[0;32m----> 2 \u001b[0m \u001b[39mdel\u001b[39;00m t[\u001b[39m0\u001b[39m]\n",
598 | "\u001b[0;31mTypeError\u001b[0m: 'tuple' object doesn't support item deletion"
599 | ]
600 | }
601 | ],
602 | "source": [
603 | "## 尝试删除元素,系统提示元素无法被删除\n",
604 | "del t[0]"
605 | ]
606 | },
607 | {
608 | "cell_type": "markdown",
609 | "id": "frank-myanmar",
610 | "metadata": {},
611 | "source": [
612 | "## 1.2.3 字典"
613 | ]
614 | },
615 | {
616 | "cell_type": "markdown",
617 | "id": "prescribed-receptor",
618 | "metadata": {},
619 | "source": [
620 | "顾名思义,字典就像现实世界中的字典,只要知道一个单词的读音,就能找到它在书中具体的位置!即我们将一个 “键(key)” 与 “值(value)” 相关联,通过键迅速检索到对应的值。要注意键必须是唯一的,这就好比两个单词如果读音一样就会出现歧义一样。\n",
621 | "\n",
622 | "字典通过花括号 `{ }` 创建,通过 `:` 符号区分键与值,通过逗号分隔。下面我们创建一个字典存储联系人的邮箱。"
623 | ]
624 | },
625 | {
626 | "cell_type": "code",
627 | "execution_count": 19,
628 | "id": "formal-policy",
629 | "metadata": {},
630 | "outputs": [],
631 | "source": [
632 | "ab = {\n",
633 | " \"XiaoHu\": \"xiaohu@RNG.com\",\n",
634 | " \"XiaoWei\": \"xiaowei@RNG.com\",\n",
635 | " \"XiaoMing\": \"xiaoming@RNG.com\"\n",
636 | "}"
637 | ]
638 | },
639 | {
640 | "cell_type": "code",
641 | "execution_count": 20,
642 | "id": "discrete-sequence",
643 | "metadata": {},
644 | "outputs": [
645 | {
646 | "name": "stdout",
647 | "output_type": "stream",
648 | "text": [
649 | "{'XiaoHu': 'xiaohu@RNG.com', 'XiaoWei': 'xiaowei@RNG.com', 'XiaoMing': 'xiaoming@RNG.com'}\n"
650 | ]
651 | }
652 | ],
653 | "source": [
654 | "print(ab)"
655 | ]
656 | },
657 | {
658 | "cell_type": "markdown",
659 | "id": "hourly-brick",
660 | "metadata": {},
661 | "source": [
662 | "字典支持以下操作:\n",
663 | "- 增:通过关键字 `[ ]` 可以向列表内增加元素\n",
664 | "- 删:通过关键字 `del` 可以删除列表内元素\n",
665 | "- 查:通过关键字 `[ ]` 可以查找列表某个位置元素\n",
666 | "- 改:通过赋值符号 `=` 可以修改某个位置的元素\n",
667 | "\n",
668 | "字典的优点是:\n",
669 | "- 快速检索到键对应的值\n",
670 | "- 字典内的键值不存在顺序关系"
671 | ]
672 | },
673 | {
674 | "cell_type": "markdown",
675 | "id": "revolutionary-remainder",
676 | "metadata": {},
677 | "source": [
678 | "### 1.2.3.1 增加元素"
679 | ]
680 | },
681 | {
682 | "cell_type": "code",
683 | "execution_count": 21,
684 | "id": "patient-investment",
685 | "metadata": {},
686 | "outputs": [
687 | {
688 | "name": "stdout",
689 | "output_type": "stream",
690 | "text": [
691 | "{'XiaoHu': 'xiaohu@RNG.com', 'XiaoWei': 'xiaowei@RNG.com', 'XiaoMing': 'xiaoming@RNG.com', 'Cryin': 'cryin@RNG.com'}\n"
692 | ]
693 | }
694 | ],
695 | "source": [
696 | "## 通过 [ ] 关键字 与赋值符号 = 向字典添加新的元素\n",
697 | "\n",
698 | "ab['Cryin'] = \"cryin@RNG.com\"\n",
699 | "print(ab)"
700 | ]
701 | },
702 | {
703 | "cell_type": "markdown",
704 | "id": "active-fellowship",
705 | "metadata": {},
706 | "source": [
707 | "### 1.2.3.2 删除元素"
708 | ]
709 | },
710 | {
711 | "cell_type": "code",
712 | "execution_count": 22,
713 | "id": "bigger-celebrity",
714 | "metadata": {},
715 | "outputs": [
716 | {
717 | "name": "stdout",
718 | "output_type": "stream",
719 | "text": [
720 | "{'XiaoHu': 'xiaohu@RNG.com', 'XiaoWei': 'xiaowei@RNG.com', 'Cryin': 'cryin@RNG.com'}\n"
721 | ]
722 | }
723 | ],
724 | "source": [
725 | "## 通过 del 关键字 删除字典中的元素\n",
726 | "\n",
727 | "del ab['XiaoMing']\n",
728 | "print(ab)"
729 | ]
730 | },
731 | {
732 | "cell_type": "markdown",
733 | "id": "still-sitting",
734 | "metadata": {},
735 | "source": [
736 | "### 1.2.3.3 查找元素"
737 | ]
738 | },
739 | {
740 | "cell_type": "code",
741 | "execution_count": 23,
742 | "id": "outdoor-processor",
743 | "metadata": {},
744 | "outputs": [
745 | {
746 | "name": "stdout",
747 | "output_type": "stream",
748 | "text": [
749 | "xiaohu@RNG.com\n"
750 | ]
751 | }
752 | ],
753 | "source": [
754 | "## 通过 [ ] 关键字根据键查找值\n",
755 | "\n",
756 | "print(ab['XiaoHu'])"
757 | ]
758 | },
759 | {
760 | "cell_type": "code",
761 | "execution_count": 24,
762 | "id": "informational-tournament",
763 | "metadata": {},
764 | "outputs": [
765 | {
766 | "name": "stdout",
767 | "output_type": "stream",
768 | "text": [
769 | "True\n",
770 | "False\n"
771 | ]
772 | }
773 | ],
774 | "source": [
775 | "## 通过 in 关键字可以查找某个键是否在字典中\n",
776 | "print('XiaoHu' in ab)\n",
777 | "print('UZI' in ab)"
778 | ]
779 | },
780 | {
781 | "cell_type": "markdown",
782 | "id": "neither-barrier",
783 | "metadata": {},
784 | "source": [
785 | "### 1.2.3.4 修改元素"
786 | ]
787 | },
788 | {
789 | "cell_type": "code",
790 | "execution_count": 25,
791 | "id": "interstate-russia",
792 | "metadata": {},
793 | "outputs": [
794 | {
795 | "name": "stdout",
796 | "output_type": "stream",
797 | "text": [
798 | "{'XiaoHu': 'xiaohu@EDG.com', 'XiaoWei': 'xiaowei@RNG.com', 'Cryin': 'cryin@RNG.com'}\n"
799 | ]
800 | }
801 | ],
802 | "source": [
803 | "## 通过 [ ] 关键字 与赋值符号 = 修改字典内的元素\n",
804 | "\n",
805 | "ab['XiaoHu'] = \"xiaohu@EDG.com\"\n",
806 | "print(ab)"
807 | ]
808 | },
809 | {
810 | "cell_type": "markdown",
811 | "id": "supported-probe",
812 | "metadata": {},
813 | "source": [
814 | "### 1.2.3.5 小例子"
815 | ]
816 | },
817 | {
818 | "cell_type": "markdown",
819 | "id": "narrative-postage",
820 | "metadata": {},
821 | "source": [
822 | "下面我们以字典为基础重新构建学生成绩管理系统:"
823 | ]
824 | },
825 | {
826 | "cell_type": "code",
827 | "execution_count": 26,
828 | "id": "fitted-trade",
829 | "metadata": {},
830 | "outputs": [
831 | {
832 | "name": "stdout",
833 | "output_type": "stream",
834 | "text": [
835 | "{'XiaoHu': 65, 'XiaoMing': 80, 'XiaoWei': 95}\n",
836 | "{'XiaoHu': 55, 'XiaoMing': 92, 'XiaoWei': 98}\n"
837 | ]
838 | }
839 | ],
840 | "source": [
841 | "## Task 1 建立学生信息管理系统\n",
842 | "\n",
843 | "Math_scores = {}\n",
844 | "Math_scores['XiaoHu'] = 65\n",
845 | "Math_scores['XiaoMing'] = 80\n",
846 | "Math_scores['XiaoWei'] = 95\n",
847 | "\n",
848 | "Chinese_scores = {}\n",
849 | "Chinese_scores['XiaoHu'] = 55\n",
850 | "Chinese_scores['XiaoMing'] = 92\n",
851 | "Chinese_scores['XiaoWei'] = 98\n",
852 | "\n",
853 | "print(Math_scores)\n",
854 | "print(Chinese_scores)"
855 | ]
856 | },
857 | {
858 | "cell_type": "code",
859 | "execution_count": 27,
860 | "id": "regular-jackson",
861 | "metadata": {},
862 | "outputs": [
863 | {
864 | "name": "stdout",
865 | "output_type": "stream",
866 | "text": [
867 | "{'XiaoHu': 95, 'XiaoMing': 75, 'XiaoWei': 92}\n",
868 | "{'XiaoHu': 85, 'XiaoMing': 71, 'XiaoWei': 93}\n"
869 | ]
870 | }
871 | ],
872 | "source": [
873 | "## Task 2 根据本次期末考试的成绩更新系统\n",
874 | "\n",
875 | "Math_scores['XiaoHu'] = 95\n",
876 | "Math_scores['XiaoMing'] = 75\n",
877 | "Math_scores['XiaoWei'] = 92\n",
878 | "\n",
879 | "Chinese_scores = {}\n",
880 | "Chinese_scores['XiaoHu'] = 85\n",
881 | "Chinese_scores['XiaoMing'] = 71\n",
882 | "Chinese_scores['XiaoWei'] = 93\n",
883 | "\n",
884 | "print(Math_scores)\n",
885 | "print(Chinese_scores)"
886 | ]
887 | },
888 | {
889 | "cell_type": "code",
890 | "execution_count": 28,
891 | "id": "global-orleans",
892 | "metadata": {},
893 | "outputs": [
894 | {
895 | "name": "stdout",
896 | "output_type": "stream",
897 | "text": [
898 | "{'XiaoHu': 95, 'XiaoWei': 92}\n",
899 | "{'XiaoHu': 85, 'XiaoWei': 93}\n"
900 | ]
901 | }
902 | ],
903 | "source": [
904 | "## Task 3 删除 XiaoMing 的信息\n",
905 | "\n",
906 | "del Math_scores['XiaoMing']\n",
907 | "del Chinese_scores['XiaoMing']\n",
908 | "\n",
909 | "print(Math_scores)\n",
910 | "print(Chinese_scores)"
911 | ]
912 | },
913 | {
914 | "cell_type": "code",
915 | "execution_count": 29,
916 | "id": "golden-composition",
917 | "metadata": {},
918 | "outputs": [
919 | {
920 | "name": "stdout",
921 | "output_type": "stream",
922 | "text": [
923 | "{'XiaoHu': 95, 'XiaoWei': 92, 'Cryin': 87}\n",
924 | "{'XiaoHu': 85, 'XiaoWei': 93, 'Cryin': 88}\n"
925 | ]
926 | }
927 | ],
928 | "source": [
929 | "## Task 4 录入 Cryin 的信息\n",
930 | "\n",
931 | "Math_scores['Cryin'] = 87\n",
932 | "Chinese_scores['Cryin'] = 88\n",
933 | "\n",
934 | "print(Math_scores)\n",
935 | "print(Chinese_scores)"
936 | ]
937 | },
938 | {
939 | "cell_type": "markdown",
940 | "id": "maritime-victim",
941 | "metadata": {},
942 | "source": [
943 | "在我们的小例子中可以观察到,字典构建的学生管理系统避免了查找元素所在位置的操作,这是字典根据“键”可以迅速找到“值”的特性决定的。"
944 | ]
945 | },
946 | {
947 | "cell_type": "markdown",
948 | "id": "nominated-transaction",
949 | "metadata": {},
950 | "source": [
951 | "## 1.2.4 集合"
952 | ]
953 | },
954 | {
955 | "cell_type": "markdown",
956 | "id": "minus-anchor",
957 | "metadata": {},
958 | "source": [
959 | "集合是用来存储无序的元素集合。通常我们只考虑元素的存在,而不考虑元素的顺序或出现次数时使用集合。\n",
960 | "\n",
961 | "集合与字典一样也通过花括号创建,但不存在 : 分隔符号。例如用集合表示中国的四个直辖市,它们无需考虑顺序与出现次数。\n",
962 | "\n",
963 | " municipalities = { \"Beijing\", \"Shanghai\", \"Tianjin\", \"Chongqing\" }\n",
964 | "\n",
965 | "注意集合中不能存在重复元素。"
966 | ]
967 | },
968 | {
969 | "cell_type": "code",
970 | "execution_count": 30,
971 | "id": "imported-destruction",
972 | "metadata": {},
973 | "outputs": [],
974 | "source": [
975 | "## 创建一个集合\n",
976 | "\n",
977 | "s = {1,2,3,4,5}"
978 | ]
979 | },
980 | {
981 | "cell_type": "markdown",
982 | "id": "stopped-logging",
983 | "metadata": {},
984 | "source": [
985 | "集合支持以下操作:\n",
986 | "- 增:通过函数 `add` 可以向集合内增加元素\n",
987 | "- 删:通过函数 `remove` 可以删除集合内元素\n",
988 | "- 查:通过关键字 `in` 可以查找某个元素是否在集合内\n",
989 | "\n",
990 | "集合的优点是:\n",
991 | "- 支持数学集合操作\n",
992 | "- 快速检索某个元素是否在集合内\n",
993 | "- 集合内的键值不存在顺序关系"
994 | ]
995 | },
996 | {
997 | "cell_type": "markdown",
998 | "id": "welcome-church",
999 | "metadata": {},
1000 | "source": [
1001 | "### 1.2.4.1 增加元素"
1002 | ]
1003 | },
1004 | {
1005 | "cell_type": "code",
1006 | "execution_count": 31,
1007 | "id": "unlike-thermal",
1008 | "metadata": {},
1009 | "outputs": [
1010 | {
1011 | "name": "stdout",
1012 | "output_type": "stream",
1013 | "text": [
1014 | "{1, 2, 3, 4, 5, 6}\n"
1015 | ]
1016 | }
1017 | ],
1018 | "source": [
1019 | "## 增加新的元素到集合中\n",
1020 | "\n",
1021 | "s.add(6)\n",
1022 | "print(s)"
1023 | ]
1024 | },
1025 | {
1026 | "cell_type": "markdown",
1027 | "id": "focused-aberdeen",
1028 | "metadata": {},
1029 | "source": [
1030 | "### 1.2.4.2 删除元素"
1031 | ]
1032 | },
1033 | {
1034 | "cell_type": "code",
1035 | "execution_count": 32,
1036 | "id": "mounted-pioneer",
1037 | "metadata": {},
1038 | "outputs": [
1039 | {
1040 | "name": "stdout",
1041 | "output_type": "stream",
1042 | "text": [
1043 | "{1, 2, 3, 4, 5}\n"
1044 | ]
1045 | }
1046 | ],
1047 | "source": [
1048 | "## 删除集合中某个元素\n",
1049 | "\n",
1050 | "s.remove(6)\n",
1051 | "print(s)"
1052 | ]
1053 | },
1054 | {
1055 | "cell_type": "markdown",
1056 | "id": "fitted-ceiling",
1057 | "metadata": {},
1058 | "source": [
1059 | "### 1.2.4.3 查找元素"
1060 | ]
1061 | },
1062 | {
1063 | "cell_type": "code",
1064 | "execution_count": 33,
1065 | "id": "coordinated-pillow",
1066 | "metadata": {},
1067 | "outputs": [
1068 | {
1069 | "name": "stdout",
1070 | "output_type": "stream",
1071 | "text": [
1072 | "True\n",
1073 | "False\n"
1074 | ]
1075 | }
1076 | ],
1077 | "source": [
1078 | "## 查找某个元素是否在集合中\n",
1079 | "print(5 in s)\n",
1080 | "print(6 in s)"
1081 | ]
1082 | },
1083 | {
1084 | "cell_type": "markdown",
1085 | "id": "animated-prevention",
1086 | "metadata": {},
1087 | "source": [
1088 | "### 1.2.4.4 数学操作"
1089 | ]
1090 | },
1091 | {
1092 | "cell_type": "markdown",
1093 | "id": "touched-harvard",
1094 | "metadata": {},
1095 | "source": [
1096 | "集合的一大特点是支持数学操作,其中包括求集合的 并集、交集 以及 亦或 操作。"
1097 | ]
1098 | },
1099 | {
1100 | "cell_type": "code",
1101 | "execution_count": 34,
1102 | "id": "motivated-yesterday",
1103 | "metadata": {},
1104 | "outputs": [],
1105 | "source": [
1106 | "## 创建另一个集合\n",
1107 | "s2 = {3,4,5,6,7}"
1108 | ]
1109 | },
1110 | {
1111 | "cell_type": "code",
1112 | "execution_count": 35,
1113 | "id": "affiliated-setup",
1114 | "metadata": {},
1115 | "outputs": [
1116 | {
1117 | "name": "stdout",
1118 | "output_type": "stream",
1119 | "text": [
1120 | "{1, 2, 3, 4, 5, 6, 7}\n"
1121 | ]
1122 | }
1123 | ],
1124 | "source": [
1125 | "## 集合并集\n",
1126 | "print(s | s2)"
1127 | ]
1128 | },
1129 | {
1130 | "cell_type": "code",
1131 | "execution_count": 36,
1132 | "id": "disabled-enzyme",
1133 | "metadata": {},
1134 | "outputs": [
1135 | {
1136 | "name": "stdout",
1137 | "output_type": "stream",
1138 | "text": [
1139 | "{3, 4, 5}\n"
1140 | ]
1141 | }
1142 | ],
1143 | "source": [
1144 | "## 集合交集\n",
1145 | "print(s & s2)"
1146 | ]
1147 | },
1148 | {
1149 | "cell_type": "code",
1150 | "execution_count": 37,
1151 | "id": "healthy-paradise",
1152 | "metadata": {},
1153 | "outputs": [
1154 | {
1155 | "name": "stdout",
1156 | "output_type": "stream",
1157 | "text": [
1158 | "{1, 2, 6, 7}\n"
1159 | ]
1160 | }
1161 | ],
1162 | "source": [
1163 | "## 集合异或,即不属于交集的部分\n",
1164 | "print(s ^ s2)"
1165 | ]
1166 | },
1167 | {
1168 | "cell_type": "markdown",
1169 | "id": "burning-contact",
1170 | "metadata": {},
1171 | "source": [
1172 | "## 1.2.5 练习"
1173 | ]
1174 | },
1175 | {
1176 | "cell_type": "markdown",
1177 | "id": "static-framework",
1178 | "metadata": {},
1179 | "source": [
1180 | "### 1.2.5.1 列表练习"
1181 | ]
1182 | },
1183 | {
1184 | "cell_type": "markdown",
1185 | "id": "previous-basin",
1186 | "metadata": {},
1187 | "source": [
1188 | "\n",
1189 | "给定两个大小分别为 m 和 n 的升序(从小到大)列表 nums1 和 nums2。请你找出并返回这两个升序列表的 中位数 。\n",
1190 | "\n",
1191 | "例子:\n",
1192 | " \n",
1193 | " 输入:nums1 = [1,2], nums2 = [3,4]\n",
1194 | " 输出:2.50000\n",
1195 | " 解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5\n",
1196 | " "
1197 | ]
1198 | },
1199 | {
1200 | "cell_type": "markdown",
1201 | "id": "instrumental-melbourne",
1202 | "metadata": {},
1203 | "source": [
1204 | "找到两个列表的中位数的思路分两步,首先合并两个升序列表为一个升序列表,然后找到升序列表中中间的数即为中位数。"
1205 | ]
1206 | },
1207 | {
1208 | "cell_type": "markdown",
1209 | "id": "express-insulin",
1210 | "metadata": {},
1211 | "source": [
1212 | "合并两个升序列表的思路很简单,因为两个列表都是升序,所以只需要判断两个列表首个元素的大小,将最小的依次放入一个新的数组中。如果其中一个数组空了,说明另一个数组中的所有元素都比之前的大,将它们合并到新数组的尾部即可。"
1213 | ]
1214 | },
1215 | {
1216 | "cell_type": "code",
1217 | "execution_count": 38,
1218 | "id": "mysterious-fairy",
1219 | "metadata": {},
1220 | "outputs": [],
1221 | "source": [
1222 | "## 定义合并两个升序列表的函数\n",
1223 | "def merge(nums1, nums2):\n",
1224 | " result = []\n",
1225 | " ## 如果两个列表都不是空的,依次比较首个元素大小\n",
1226 | " while len(nums1) > 0 and len(nums2) > 0:\n",
1227 | " ## 如果第一个列表首个元素更小\n",
1228 | " if nums1[0] < nums2[0]:\n",
1229 | " ## 将 nums1 列表的首个元素放入 result 列表\n",
1230 | " result.append(nums1[0])\n",
1231 | " nums1 = nums1[1:]\n",
1232 | " ## 如果第 nums2 列表首个元素更小\n",
1233 | " else:\n",
1234 | " ## 将 nums2 列表的首个元素放入 result 列表\n",
1235 | " result.append(nums2[0])\n",
1236 | " nums2 = nums2[1:]\n",
1237 | " ## 如果某个列表空了,将非空的数组合并到 result 尾部\n",
1238 | " result = result + nums1\n",
1239 | " result = result + nums2\n",
1240 | " return result"
1241 | ]
1242 | },
1243 | {
1244 | "cell_type": "code",
1245 | "execution_count": 39,
1246 | "id": "extraordinary-contract",
1247 | "metadata": {},
1248 | "outputs": [],
1249 | "source": [
1250 | "## 在合并后的列表中寻找中位数\n",
1251 | "def find_medium(nums):\n",
1252 | " half = len(nums) // 2\n",
1253 | " ## 如果列表长度为偶数,则取中间两个数的平均值\n",
1254 | " if len(nums) % 2 == 0:\n",
1255 | " return (nums[half - 1] + nums[half]) / 2\n",
1256 | " ## 如果列表长度为奇数,则取最中间数\n",
1257 | " else:\n",
1258 | " return nums[half]"
1259 | ]
1260 | },
1261 | {
1262 | "cell_type": "code",
1263 | "execution_count": 40,
1264 | "id": "metric-natural",
1265 | "metadata": {},
1266 | "outputs": [
1267 | {
1268 | "data": {
1269 | "text/plain": [
1270 | "2.5"
1271 | ]
1272 | },
1273 | "execution_count": 40,
1274 | "metadata": {},
1275 | "output_type": "execute_result"
1276 | }
1277 | ],
1278 | "source": [
1279 | "nums1 = [1,2]\n",
1280 | "nums2 = [3,4]\n",
1281 | "find_medium(merge(nums1, nums2))"
1282 | ]
1283 | },
1284 | {
1285 | "cell_type": "markdown",
1286 | "id": "alpha-factory",
1287 | "metadata": {},
1288 | "source": [
1289 | "### 1.2.5.2 字典练习"
1290 | ]
1291 | },
1292 | {
1293 | "cell_type": "markdown",
1294 | "id": "forbidden-family",
1295 | "metadata": {},
1296 | "source": [
1297 | "\n",
1298 | "给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数。\n",
1299 | "例子:\n",
1300 | " \n",
1301 | " 输入:nums = [2,7,11,15], target = 9\n",
1302 | " 输出:[2,7]\n",
1303 | " 解释:因为 nums[0] + nums[1] == 9 ,返回 [2, 7] 。\n",
1304 | " "
1305 | ]
1306 | },
1307 | {
1308 | "cell_type": "markdown",
1309 | "id": "partial-cornell",
1310 | "metadata": {},
1311 | "source": [
1312 | "本练习在上一节中我们已经实现过,思路是通过两重 for-in 循环寻找两个和为 target 的整数:"
1313 | ]
1314 | },
1315 | {
1316 | "cell_type": "code",
1317 | "execution_count": 41,
1318 | "id": "cooked-filename",
1319 | "metadata": {},
1320 | "outputs": [],
1321 | "source": [
1322 | "def check_sum(num1, num2, target):\n",
1323 | " a = num1\n",
1324 | " b = num2\n",
1325 | " return a + b == target\n",
1326 | "\n",
1327 | "def twosum(nums, target):\n",
1328 | " finded = False\n",
1329 | " for a in nums:\n",
1330 | " for b in nums:\n",
1331 | " if check_sum(a,b,target):\n",
1332 | " return [a,b]"
1333 | ]
1334 | },
1335 | {
1336 | "cell_type": "code",
1337 | "execution_count": 42,
1338 | "id": "pointed-familiar",
1339 | "metadata": {},
1340 | "outputs": [
1341 | {
1342 | "data": {
1343 | "text/plain": [
1344 | "[2, 7]"
1345 | ]
1346 | },
1347 | "execution_count": 42,
1348 | "metadata": {},
1349 | "output_type": "execute_result"
1350 | }
1351 | ],
1352 | "source": [
1353 | "nums = [2,7,11,15]\n",
1354 | "twosum(nums, 9)"
1355 | ]
1356 | },
1357 | {
1358 | "cell_type": "markdown",
1359 | "id": "stretch-andrews",
1360 | "metadata": {},
1361 | "source": [
1362 | "在这里我们简要引入时间复杂度的概念,它在计算机科学与数据科学领域发挥着不可替代的作用。我们经常会看到 $O(n),O(log(n)),O(n^k)$ 等符号,它们表示程序运行时间与程序输入大小的关系。\n",
1363 | "\n",
1364 | "其中 $O(n)$ 表示程序运行时间跟随程序输入大小线性增长。就好比我们在赛百味买一个 6 英寸三明治是 18 块钱,买一个 12 英寸的三明治是 36 块钱……\n",
1365 | "\n",
1366 | "$O(n^2)$ 表示程序运行时间跟随程序输入大小平方增长。就像我们在必胜客买一个 12 英寸的披萨的价格大概是 6 英寸披萨价格的四倍……"
1367 | ]
1368 | },
1369 | {
1370 | "cell_type": "code",
1371 | "execution_count": 43,
1372 | "id": "behavioral-farming",
1373 | "metadata": {},
1374 | "outputs": [
1375 | {
1376 | "name": "stdout",
1377 | "output_type": "stream",
1378 | "text": [
1379 | "\u001b[33mDEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1380 | "Collecting numpy\n",
1381 | " Downloading numpy-1.23.1-cp39-cp39-macosx_11_0_arm64.whl (13.3 MB)\n",
1382 | " |████████████████████████████████| 13.3 MB 6.7 MB/s \n",
1383 | "\u001b[?25hCollecting matplotlib\n",
1384 | " Downloading matplotlib-3.5.2-cp39-cp39-macosx_11_0_arm64.whl (7.2 MB)\n",
1385 | " |████████████████████████████████| 7.2 MB 7.6 MB/s \n",
1386 | "\u001b[?25hCollecting cycler>=0.10\n",
1387 | " Downloading cycler-0.11.0-py3-none-any.whl (6.4 kB)\n",
1388 | "Collecting fonttools>=4.22.0\n",
1389 | " Downloading fonttools-4.34.4-py3-none-any.whl (944 kB)\n",
1390 | " |████████████████████████████████| 944 kB 139.0 MB/s \n",
1391 | "\u001b[?25hCollecting pillow>=6.2.0\n",
1392 | " Downloading Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl (2.8 MB)\n",
1393 | " |████████████████████████████████| 2.8 MB 21.1 MB/s \n",
1394 | "\u001b[?25hCollecting kiwisolver>=1.0.1\n",
1395 | " Downloading kiwisolver-1.4.3-cp39-cp39-macosx_11_0_arm64.whl (63 kB)\n",
1396 | " |████████████████████████████████| 63 kB 12.6 MB/s \n",
1397 | "\u001b[?25hRequirement already satisfied: python-dateutil>=2.7 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (2.8.2)\n",
1398 | "Requirement already satisfied: pyparsing>=2.2.1 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (3.0.9)\n",
1399 | "Requirement already satisfied: packaging>=20.0 in /opt/homebrew/lib/python3.9/site-packages (from matplotlib) (21.3)\n",
1400 | "Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n",
1401 | "Installing collected packages: pillow, numpy, kiwisolver, fonttools, cycler, matplotlib\n",
1402 | "\u001b[33m DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1403 | "\u001b[33m DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1404 | "\u001b[33m DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1405 | "\u001b[33m DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1406 | "\u001b[33m DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1407 | "\u001b[33mDEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621\u001b[0m\n",
1408 | "Successfully installed cycler-0.11.0 fonttools-4.34.4 kiwisolver-1.4.3 matplotlib-3.5.2 numpy-1.23.1 pillow-9.2.0\n",
1409 | "\u001b[33mWARNING: You are using pip version 21.3.1; however, version 22.1.2 is available.\n",
1410 | "You should consider upgrading via the '/opt/homebrew/opt/python@3.9/bin/python3.9 -m pip install --upgrade pip' command.\u001b[0m\n"
1411 | ]
1412 | },
1413 | {
1414 | "data": {
1415 | "text/plain": [
1416 | "Text(0, 0.5, 'Running time')"
1417 | ]
1418 | },
1419 | "execution_count": 43,
1420 | "metadata": {},
1421 | "output_type": "execute_result"
1422 | },
1423 | {
1424 | "data": {
1425 | "image/png": "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",
1426 | "text/plain": [
1427 | ""
1428 | ]
1429 | },
1430 | "metadata": {
1431 | "needs_background": "light"
1432 | },
1433 | "output_type": "display_data"
1434 | }
1435 | ],
1436 | "source": [
1437 | "## 本段代码绘图使用无需理解\n",
1438 | "! pip3 install numpy matplotlib\n",
1439 | "import numpy as np\n",
1440 | "import matplotlib.pyplot as plt \n",
1441 | "x = np.arange(0,5,0.1)\n",
1442 | "y = x\n",
1443 | "plt.plot(x,y)\n",
1444 | "y = x**2\n",
1445 | "plt.plot(x,y)\n",
1446 | "plt.xlabel('Imput size')\n",
1447 | "plt.ylabel('Running time')"
1448 | ]
1449 | },
1450 | {
1451 | "cell_type": "markdown",
1452 | "id": "brilliant-radical",
1453 | "metadata": {},
1454 | "source": [
1455 | "在上面的图中可以直观看到 平方复杂度 随着时间增长 运行时间急剧增加,因此能够把复杂度从 $O(n^2)$ 降低到 $O(n)$ 甚至 $O(log(n))$ 带来的增益是巨大的。尤其是在数据科学领域,程序往往需要处理上千万条数据,不同复杂度的代码运行时间差距非常显著。"
1456 | ]
1457 | },
1458 | {
1459 | "cell_type": "markdown",
1460 | "id": "brief-oakland",
1461 | "metadata": {},
1462 | "source": [
1463 | "那么在上述程序中,输入列表的大小为 4,在最坏情况下 twosum 函数中的两个 for-in 循环一共执行 16 次 check_sum 操作,因此该算法的复杂度是$O(n^2)$。下面我们用 字典 优化代码复杂度为 $O(n)$,思路是遍历一次列表并将遍历过的元素值存储到字典中,若有字典中的元素值与列表中的元素值求和为target,则返回这两个值。"
1464 | ]
1465 | },
1466 | {
1467 | "cell_type": "code",
1468 | "execution_count": 44,
1469 | "id": "fewer-income",
1470 | "metadata": {},
1471 | "outputs": [],
1472 | "source": [
1473 | "def twosum(nums, target):\n",
1474 | " hashtable = {}\n",
1475 | " for num in nums:\n",
1476 | " if num in hashtable:\n",
1477 | " return [hashtable[num], num]\n",
1478 | " hashtable[target - num] = num"
1479 | ]
1480 | },
1481 | {
1482 | "cell_type": "code",
1483 | "execution_count": 45,
1484 | "id": "hearing-latter",
1485 | "metadata": {},
1486 | "outputs": [
1487 | {
1488 | "data": {
1489 | "text/plain": [
1490 | "[2, 7]"
1491 | ]
1492 | },
1493 | "execution_count": 45,
1494 | "metadata": {},
1495 | "output_type": "execute_result"
1496 | }
1497 | ],
1498 | "source": [
1499 | "twosum(nums,9)"
1500 | ]
1501 | }
1502 | ],
1503 | "metadata": {
1504 | "kernelspec": {
1505 | "display_name": "Python 3.9.7 ('base')",
1506 | "language": "python",
1507 | "name": "python3"
1508 | },
1509 | "language_info": {
1510 | "codemirror_mode": {
1511 | "name": "ipython",
1512 | "version": 3
1513 | },
1514 | "file_extension": ".py",
1515 | "mimetype": "text/x-python",
1516 | "name": "python",
1517 | "nbconvert_exporter": "python",
1518 | "pygments_lexer": "ipython3",
1519 | "version": "3.9.7"
1520 | },
1521 | "notify_time": "10",
1522 | "toc": {
1523 | "base_numbering": 1,
1524 | "nav_menu": {},
1525 | "number_sections": false,
1526 | "sideBar": true,
1527 | "skip_h1_title": true,
1528 | "title_cell": "Table of Contents",
1529 | "title_sidebar": "Contents",
1530 | "toc_cell": false,
1531 | "toc_position": {
1532 | "height": "calc(100% - 180px)",
1533 | "left": "10px",
1534 | "top": "150px",
1535 | "width": "189.25271606445312px"
1536 | },
1537 | "toc_section_display": true,
1538 | "toc_window_display": true
1539 | },
1540 | "vscode": {
1541 | "interpreter": {
1542 | "hash": "c6e4e9f98eb68ad3b7c296f83d20e6de614cb42e90992a65aa266555a3137d0d"
1543 | }
1544 | }
1545 | },
1546 | "nbformat": 4,
1547 | "nbformat_minor": 5
1548 | }
1549 |
--------------------------------------------------------------------------------
/3. Python 面向对象编程.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "legislative-launch",
6 | "metadata": {},
7 | "source": [
8 | "# Python 面向对象编程"
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "id": "demonstrated-volunteer",
14 | "metadata": {},
15 | "source": [
16 | "在北宋时期,毕昇发明了活字印刷术。他先将文字做成一个个汉字模具,然后按照稿件把单字挑选出来,排列在字盘内,涂墨印刷成书,印完后再将字模拆出,留待下次排印时再次使用。活字印刷术相对于文字书写更加简洁高效,它对印刷业的兴起发挥了重大作用,甚至推动了欧洲文艺复兴的发展。"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "id": "incident-senegal",
22 | "metadata": {},
23 | "source": [
24 | "Python 是一种基于面向对象设计的编程语言,它使用“类”与“对象”进行编程。这里“类”就好比汉字模具,“对象”就好比印刷完的书籍。你不需要一次又一次书写复杂重复的程序,只需要提前编写好需要的类,然后通过类产生具有特定功能的对象即可,这大大提高了 Python 编程的简洁性。 "
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "id": "related-malawi",
30 | "metadata": {},
31 | "source": [
32 | "下面我们就通过面向对象的角度重新审视 Python 宇宙,相信你可以感受到面向对象带来的代码简化与效率提升。"
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "id": "concerned-tuner",
38 | "metadata": {},
39 | "source": [
40 | "## 1.3.1 面向对象编程理论"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "id": "exact-difficulty",
46 | "metadata": {},
47 | "source": [
48 | "在之前的代码中,我们往往采用典型的面向过程编程方式,定义很多函数与变量:\n",
49 | "\n",
50 | " ## 定义函数:\n",
51 | " 函数1\n",
52 | " 函数2\n",
53 | " 函数3\n",
54 | " 函数4\n",
55 | " \n",
56 | " ## 定义变量:\n",
57 | " 变量1\n",
58 | " 变量2\n",
59 | " 变量3\n",
60 | " 变量4\n",
61 | " \n",
62 | " ## 通过变量与函数完成操作\n",
63 | " 变量3 = 函数1(变量1, 变量2)\n",
64 | " 变量5 = 函数2(变量3, 变量4)\n",
65 | " \n",
66 | "然而当我们要实现的功能越来越复杂,需要添加的函数与变量也就越来越多。每个函数都有不同的功能,有特定的参数与返回结果,每个变量也有不同的表示意义,程序会变得越来越难以维护。而面向对象通过类与对象的方式解决问题:\n",
67 | "\n",
68 | " ## 根据功能定义类1\n",
69 | " 类1:\n",
70 | " 类函数1\n",
71 | " 变量:\n",
72 | " 变量1\n",
73 | " 变量2\n",
74 | " \n",
75 | " ## 根据功能定义类2\n",
76 | " 类2:\n",
77 | " 类函数2\n",
78 | " 类函数3\n",
79 | " 变量:\n",
80 | " 变量3\n",
81 | " 变量4\n",
82 | " 变量5\n",
83 | " \n",
84 | " ## 通过对象完成操作\n",
85 | " 对象1 = 类1()\n",
86 | " 对象2 = 类2()\n",
87 | " 对象2.变量5 = 对象2.函数2(对象1.函数1())\n",
88 | " \n",
89 | " \n",
90 | "面向对象编程的出现,使得变量和函数可以根据功能进行整理分类,通过面向对象的模块化编程,大大减轻了复杂程序的设计与维护负担。"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "id": "administrative-logging",
96 | "metadata": {},
97 | "source": [
98 | "### 1.3.1.1 对象"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "id": "contrary-calgary",
104 | "metadata": {},
105 | "source": [
106 | "在 Python 中一切都是对象,就像在现实世界中一切都是对象。\n",
107 | "\n",
108 | "- 在现实中:对象可以是有型的,例如一粒米、一名学生、一辆汽车,甚至一个星球。它也可以是无形的,例如一次演出,一场球赛,一次出差。对象可以简单也可以复杂,复杂的对象可以由许多简单的对象构成,整个世界也可以被认为是一个非常复杂的对象。\n",
109 | "\n",
110 | "- 在 Python 中:对象可以是有型的,例如一个常量,一个变量,一个序列或字典。它也可以是无形的,例如一个函数。对象可以简单也可以复杂,复杂的对象可以由许多的简单对象组成,整个 Python 程序也可以被当作一个对象。\n",
111 | "\n",
112 | "无论在现实中或 Python 中,对象都具有以下三个特性:\n",
113 | "\n",
114 | "- 每个对象都有一个独特的名字以区别于其他对象。\n",
115 | "- 有属性来描述它的某些特征。\n",
116 | "- 有一组操作,每个操作决定对象的一种行为。"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "id": "widespread-fourth",
122 | "metadata": {},
123 | "source": [
124 | "### 1.3.1.2 类"
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "id": "vocal-communication",
130 | "metadata": {},
131 | "source": [
132 | "类是用来定义对象的 “模板”。\n",
133 | "\n",
134 | "- 在现实中:类是一组具有相同属性和行为的对象的抽象。例如张三、李四虽然每个人有不同的性格与职业,但他们的基本特征是相似的,都有鼻子有眼能吃饭,因此我们统称他们为“人”类,而每一个人就是一个对象。\n",
135 | "- 在 Python 中:类是一组具有相同数据和操作的对象的模板集合。例如“学生”类可以由学号、姓名、性别、成绩等表示其属性的数据项和对这些数据的录入、修改和显示等操作组成,而每一个特定的学生例如 XiaoHu 就是一个对象。"
136 | ]
137 | },
138 | {
139 | "cell_type": "markdown",
140 | "id": "recorded-irrigation",
141 | "metadata": {},
142 | "source": [
143 | "### 1.3.1.3 面向对象编程的特点"
144 | ]
145 | },
146 | {
147 | "cell_type": "markdown",
148 | "id": "clinical-checklist",
149 | "metadata": {},
150 | "source": [
151 | "面向对象编程有以下几个基本特征:\n",
152 | "\n",
153 | "- 抽象:是将有关事物的特征归纳、集中的过程。通过总结不同“对象”的主要特性设计一个“类”,只强调感兴趣的信息,忽略了与主题无关的信息。\n",
154 | "- 封装:是把数据和操作集中在对象内部,并尽可能隐藏对象的内部细节。对象像一个黑匣子,你只要知道它提供的功能,不需要了解其内部的实现方式。\n",
155 | "- 继承:是指一个类可以继承另一个类的特征与功能,并添加自己的特征。例如“吉士堡”继承了“汉堡”类,它有面包、菜与肉,但也有独特的一片芝士。\n",
156 | "- 多态:指不同的对象进行相同操作时产生多种不同的行为方式。例如“打开”电风扇它会旋转,“打开”电脑屏幕会亮,“打开”抽屉柜子门会开,同样是打开操作,不同对象收到指令后的行为方式是不同的。"
157 | ]
158 | },
159 | {
160 | "cell_type": "markdown",
161 | "id": "automotive-draft",
162 | "metadata": {},
163 | "source": [
164 | "## 1.3.2 Python 面向对象编程"
165 | ]
166 | },
167 | {
168 | "cell_type": "markdown",
169 | "id": "czech-miniature",
170 | "metadata": {},
171 | "source": [
172 | "到目前为止,我们接触的变量、运算符、函数等概念来源于 “面向过程” 的编程方式。在上一节中,你可能会对 `names.append('Cryin')` 这种写法感到疑惑,为什么序列变量 names 可以通过符号 . 调用 append 函数?这种编程方式便是面向对象编程,在这里 names 是一个对象,对象拥有很多类似 append 的函数,每个对象都属于某一个类。"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "id": "brilliant-shock",
178 | "metadata": {},
179 | "source": [
180 | "下面我们将介绍 Python 中的面向对象编程方法,并以上一节中的学生成绩管理系统为例方便大家理解。"
181 | ]
182 | },
183 | {
184 | "cell_type": "markdown",
185 | "id": "absent-elite",
186 | "metadata": {},
187 | "source": [
188 | "### 1.3.2.1 Python 类与对象"
189 | ]
190 | },
191 | {
192 | "cell_type": "markdown",
193 | "id": "indian-playback",
194 | "metadata": {},
195 | "source": [
196 | "Python 使用 class 关键字定义类,类似函数,下面的缩进部分构成了类的主体:"
197 | ]
198 | },
199 | {
200 | "cell_type": "code",
201 | "execution_count": 1,
202 | "id": "whole-translation",
203 | "metadata": {},
204 | "outputs": [],
205 | "source": [
206 | "## 创建一个 student 类\n",
207 | "class student():\n",
208 | " pass"
209 | ]
210 | },
211 | {
212 | "cell_type": "markdown",
213 | "id": "convertible-alias",
214 | "metadata": {},
215 | "source": [
216 | "使用类的名字和一对括号可以创建类的对象:"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": 2,
222 | "id": "marked-hello",
223 | "metadata": {},
224 | "outputs": [
225 | {
226 | "name": "stdout",
227 | "output_type": "stream",
228 | "text": [
229 | "\n",
230 | "\n"
231 | ]
232 | }
233 | ],
234 | "source": [
235 | "## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu\n",
236 | "xiaohu = student()\n",
237 | "xiaoming = student()\n",
238 | "\n",
239 | "print(type(xiaohu))\n",
240 | "print(type(xiaoming))"
241 | ]
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "id": "prerequisite-ideal",
246 | "metadata": {},
247 | "source": [
248 | "### 1.3.2.2 类与对象中的变量"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "id": "injured-difference",
254 | "metadata": {},
255 | "source": [
256 | "我们提到类与对象都有包含一组属性与方法,在 Python 中类的变量用于表示类的属性。`student` 表示学生类,在我们的系统中我们只关注学生的姓名、数学成绩和语文成绩而不考虑其他,分别用类变量 `name`, `Math_score`, `Chinese_score` 表示。这体现了面向对象编程的”抽象性“。"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": 3,
262 | "id": "severe-reset",
263 | "metadata": {},
264 | "outputs": [],
265 | "source": [
266 | "## 创建一个 student 类\n",
267 | "class student():\n",
268 | " ## 类的内部定义三个内部变量,并定义他们的初始值\n",
269 | " name = 'Undefined'\n",
270 | " Math_score = None\n",
271 | " Chinese_score = None"
272 | ]
273 | },
274 | {
275 | "cell_type": "markdown",
276 | "id": "distant-lighting",
277 | "metadata": {},
278 | "source": [
279 | "在 Python 中对象拥有与类相同的数据和操作,因此通过类创建的对象也拥有相同的变量。我们使用 `.` 符号来引用对象或类的变量与函数:"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": 4,
285 | "id": "manual-montreal",
286 | "metadata": {},
287 | "outputs": [
288 | {
289 | "name": "stdout",
290 | "output_type": "stream",
291 | "text": [
292 | "Undefined\n",
293 | "None\n",
294 | "None\n"
295 | ]
296 | }
297 | ],
298 | "source": [
299 | "## 使用 类的名字 student 与 括号() 可以创建类的对象 xiaohu\n",
300 | "xiaohu = student()\n",
301 | "## 使用 . 符号引用对象xiaohu的变量name、Math_score、Chinese_score\n",
302 | "print(xiaohu.name)\n",
303 | "print(xiaohu.Math_score)\n",
304 | "print(xiaohu.Chinese_score)"
305 | ]
306 | },
307 | {
308 | "cell_type": "markdown",
309 | "id": "valid-attribute",
310 | "metadata": {},
311 | "source": [
312 | "这里我们通过类创建对象还仅仅是一个初始值,这里我们可以通过赋值符号改变对象内数据的值:"
313 | ]
314 | },
315 | {
316 | "cell_type": "code",
317 | "execution_count": 5,
318 | "id": "black-pakistan",
319 | "metadata": {},
320 | "outputs": [
321 | {
322 | "name": "stdout",
323 | "output_type": "stream",
324 | "text": [
325 | "XiaoHu\n",
326 | "65\n",
327 | "55\n"
328 | ]
329 | }
330 | ],
331 | "source": [
332 | "## 通过赋值符号改变对象内变量的值\n",
333 | "xiaohu.name = 'XiaoHu'\n",
334 | "xiaohu.Math_score = 65\n",
335 | "xiaohu.Chinese_score = 55\n",
336 | "\n",
337 | "print(xiaohu.name)\n",
338 | "print(xiaohu.Math_score)\n",
339 | "print(xiaohu.Chinese_score)"
340 | ]
341 | },
342 | {
343 | "cell_type": "markdown",
344 | "id": "removed-warren",
345 | "metadata": {},
346 | "source": [
347 | "在这里我们要注意区分两个概念,类变量与对象变量,在上述代码中 `student.name` 是类变量,`xiaohu.name` 是对象变量。\n",
348 | "\n",
349 | "- 类变量属于类,更改类变量会影响所有后续由该类创建对象的属性。\n",
350 | "- 对象变量属于对象,更改对象变量只影响该对象的属性。"
351 | ]
352 | },
353 | {
354 | "cell_type": "code",
355 | "execution_count": 6,
356 | "id": "south-tongue",
357 | "metadata": {},
358 | "outputs": [
359 | {
360 | "name": "stdout",
361 | "output_type": "stream",
362 | "text": [
363 | "XiaoMing\n",
364 | "XiaoHu\n"
365 | ]
366 | }
367 | ],
368 | "source": [
369 | "## 更改对象变量只影响该对象的属性。\n",
370 | "xiaoming = student()\n",
371 | "## 修改 xiaoming.name,xiaohu 的属性不受影响\n",
372 | "xiaoming.name = 'XiaoMing'\n",
373 | "print(xiaoming.name)\n",
374 | "print(xiaohu.name)"
375 | ]
376 | },
377 | {
378 | "cell_type": "code",
379 | "execution_count": 7,
380 | "id": "loose-albuquerque",
381 | "metadata": {},
382 | "outputs": [
383 | {
384 | "name": "stdout",
385 | "output_type": "stream",
386 | "text": [
387 | "Undefined\n",
388 | "Change Name\n"
389 | ]
390 | }
391 | ],
392 | "source": [
393 | "## 更改类变量会影响所有后续由该类创建对象的属性。\n",
394 | "xiaoming = student()\n",
395 | "print(xiaoming.name)\n",
396 | "\n",
397 | "## 修改 student.name 再次创建新对象 xiaoming\n",
398 | "student.name = 'Change Name'\n",
399 | "xiaoming = student()\n",
400 | "\n",
401 | "## xiaoming.name 不再是 undefined 而是 change name\n",
402 | "print(xiaoming.name)"
403 | ]
404 | },
405 | {
406 | "cell_type": "markdown",
407 | "id": "elder-memorial",
408 | "metadata": {},
409 | "source": [
410 | "### 1.3.2.3 类与对象中的函数"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "id": "earlier-integer",
416 | "metadata": {},
417 | "source": [
418 | "在 Python 中类函数用于表示类的操作,它又被称作为“方法”。它们与之前我们学到的函数类似,但是类函数必须有一个额外的 self 参数:"
419 | ]
420 | },
421 | {
422 | "cell_type": "code",
423 | "execution_count": 8,
424 | "id": "heavy-jewel",
425 | "metadata": {},
426 | "outputs": [],
427 | "source": [
428 | "class student():\n",
429 | " ## 定义类函数时要有一个特殊的 self 参数\n",
430 | " def print_name(self,):\n",
431 | " print(self.name)\n",
432 | " \n",
433 | " name = 'Undefined'\n",
434 | " Math_score = None\n",
435 | " Chinese_score = None"
436 | ]
437 | },
438 | {
439 | "cell_type": "code",
440 | "execution_count": 9,
441 | "id": "occasional-paint",
442 | "metadata": {},
443 | "outputs": [
444 | {
445 | "name": "stdout",
446 | "output_type": "stream",
447 | "text": [
448 | "Xiaohu\n"
449 | ]
450 | }
451 | ],
452 | "source": [
453 | "xiaohu = student()\n",
454 | "xiaohu.name = 'Xiaohu'\n",
455 | "xiaohu.print_name()"
456 | ]
457 | },
458 | {
459 | "cell_type": "markdown",
460 | "id": "authentic-williams",
461 | "metadata": {},
462 | "source": [
463 | "self 函数用于在类的内部指向对象本身,它是用于连接 类 与 对象 的工具,也是 Python 面向对象编程“多态”特性的一种体现。\n",
464 | "\n",
465 | "例如在上述代码,我们使用 student 类产生对象 xiaohu,那么 self 就代指 xiaohu;如果我们产生对象 xiaoming,那么 self 就会自动代指 xiaoming。因此 self 参数可以根据不同对象产生不同操作,这体现了面向对象编程的“多态性”。"
466 | ]
467 | },
468 | {
469 | "cell_type": "markdown",
470 | "id": "daily-impact",
471 | "metadata": {},
472 | "source": [
473 | "我们还可以给 student 创建一个用于更改成绩的方法,这样我们后续就不需要通过赋值符号更改对象内的数据:"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": 10,
479 | "id": "colonial-craps",
480 | "metadata": {},
481 | "outputs": [],
482 | "source": [
483 | "class student():\n",
484 | " ## 定义一个修改对象数据值的函数\n",
485 | " def change_score(self, course_name, score):\n",
486 | " if course_name == 'Math':\n",
487 | " self.Math_score = score\n",
488 | " elif course_name == 'Chinese':\n",
489 | " self.Chinese_score = score\n",
490 | " ## 如果输入的 course_name 不是 Math 或者 Chinese,则输出错误信息\n",
491 | " else:\n",
492 | " print(course_name, \" course is still not in current system\")\n",
493 | " \n",
494 | " def print_name(self,):\n",
495 | " print(self.name)\n",
496 | " \n",
497 | " name = 'Undefined'\n",
498 | " Math_score = None\n",
499 | " Chinese_score = None"
500 | ]
501 | },
502 | {
503 | "cell_type": "code",
504 | "execution_count": 11,
505 | "id": "split-burner",
506 | "metadata": {},
507 | "outputs": [
508 | {
509 | "name": "stdout",
510 | "output_type": "stream",
511 | "text": [
512 | "Physics course is still not in current system\n"
513 | ]
514 | }
515 | ],
516 | "source": [
517 | "xiaohu = student()\n",
518 | "xiaohu.name = 'Xiaohu'\n",
519 | "xiaohu.change_score('Math', 65)\n",
520 | "xiaohu.change_score('Chinese',55)\n",
521 | "xiaohu.change_score('Physics',48)"
522 | ]
523 | },
524 | {
525 | "cell_type": "markdown",
526 | "id": "pointed-asset",
527 | "metadata": {},
528 | "source": [
529 | "随着系统的迭代,系统的复杂度将会直线上升。假设当我们有了十多种课程后,采用 change_score 函数要比直接为一个个课程的成绩赋值更加优雅,用户不再需要了解 student 类中有定义哪些变量等复杂细节,只需要了解 change_score 函数的用法便可以更改学生成绩,这体现了面向对象编程的“封装性”。"
530 | ]
531 | },
532 | {
533 | "cell_type": "markdown",
534 | "id": "fantastic-inspector",
535 | "metadata": {},
536 | "source": [
537 | "### 1.3.2.4 \\_\\_init\\_\\_ 方法"
538 | ]
539 | },
540 | {
541 | "cell_type": "markdown",
542 | "id": "surprised-jimmy",
543 | "metadata": {},
544 | "source": [
545 | "在之前的代码中,我们采用赋值符号来为对象产生初始值:\n",
546 | "\n",
547 | " xiaohu.name = 'XiaoHu'\n",
548 | " xiaohu.Math_score = 65\n",
549 | " xiaohu.Chinese_score = 55\n",
550 | " \n",
551 | "然而这种方式或许有些麻烦,其实 Python 类中有一种 `__init__` 方法专门用于初始化对象。这个方法在通过类创建对象时被自动调用,并按照你的想法初始化该对象。下面我们通过 `__init__` 方法重新定义 student 类:\n",
552 | "\n"
553 | ]
554 | },
555 | {
556 | "cell_type": "code",
557 | "execution_count": 12,
558 | "id": "standard-american",
559 | "metadata": {},
560 | "outputs": [],
561 | "source": [
562 | "class student():\n",
563 | " ## 定义 __init__ 方法,通过该方法的参数输入初始值,在该方法内部为变量赋值\n",
564 | " def __init__(self, name, Math_score, Chinese_score):\n",
565 | " self.name = name\n",
566 | " self.Math_score = Math_score\n",
567 | " self.Chinese_score = Chinese_score\n",
568 | " \n",
569 | " def change_score(self, course_name, score):\n",
570 | " if course_name == 'Math':\n",
571 | " self.Math_score = score\n",
572 | " elif course_name == 'Chinese':\n",
573 | " self.Chinese_score = score\n",
574 | " ## 如果输入的 course_name 不是 Math 或者 Chinese,则输出错误信息\n",
575 | " else:\n",
576 | " print(course_name, \" course is still not in current system\")\n",
577 | " \n",
578 | " def print_name(self,):\n",
579 | " print(self.name)\n",
580 | " \n",
581 | " name = 'Undefined'\n",
582 | " Math_score = None\n",
583 | " Chinese_score = None"
584 | ]
585 | },
586 | {
587 | "cell_type": "markdown",
588 | "id": "american-swiss",
589 | "metadata": {},
590 | "source": [
591 | "在定义了 `__init__` 方法后,我们通过在类后面的小括号内传递参数的方式初始化对象:"
592 | ]
593 | },
594 | {
595 | "cell_type": "code",
596 | "execution_count": 13,
597 | "id": "level-status",
598 | "metadata": {},
599 | "outputs": [
600 | {
601 | "name": "stdout",
602 | "output_type": "stream",
603 | "text": [
604 | "XiaoHu\n"
605 | ]
606 | }
607 | ],
608 | "source": [
609 | "## \n",
610 | "xiaohu = student('XiaoHu',65,55)\n",
611 | "xiaohu.print_name()"
612 | ]
613 | },
614 | {
615 | "cell_type": "markdown",
616 | "id": "incorporate-taxation",
617 | "metadata": {},
618 | "source": [
619 | "## 1.3.3 万物皆对象"
620 | ]
621 | },
622 | {
623 | "cell_type": "markdown",
624 | "id": "uniform-abortion",
625 | "metadata": {},
626 | "source": [
627 | "对象是 Python 中最核心的概念,犹如道教中 “一生二,二生三,三生万物”,Python 中万物皆源于对象。下面我们在面向对象编程的角度回顾之前学习的变量、函数以及数据结构。"
628 | ]
629 | },
630 | {
631 | "cell_type": "markdown",
632 | "id": "neither-studio",
633 | "metadata": {},
634 | "source": [
635 | "### 1.3.3.1 重识变量"
636 | ]
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "id": "nasty-fellowship",
641 | "metadata": {},
642 | "source": [
643 | "在 Python 中所有变量都是对象,下面我们创建一个 int 变量,它有 bit_lenth, conjugate, to_byte, from_byte 等方法。我们测试一下 to_byte 方法: "
644 | ]
645 | },
646 | {
647 | "cell_type": "code",
648 | "execution_count": 14,
649 | "id": "reasonable-caribbean",
650 | "metadata": {},
651 | "outputs": [
652 | {
653 | "data": {
654 | "text/plain": [
655 | "int"
656 | ]
657 | },
658 | "execution_count": 14,
659 | "metadata": {},
660 | "output_type": "execute_result"
661 | }
662 | ],
663 | "source": [
664 | "variable = 1\n",
665 | "type(variable)"
666 | ]
667 | },
668 | {
669 | "cell_type": "markdown",
670 | "id": "above-convention",
671 | "metadata": {},
672 | "source": [
673 | "to_byte 将 int 对象转化成 byte 对象 b'\\x00x\\01' 因为整数 1 的二进制编码是 0001。"
674 | ]
675 | },
676 | {
677 | "cell_type": "code",
678 | "execution_count": 15,
679 | "id": "freelance-briefing",
680 | "metadata": {},
681 | "outputs": [
682 | {
683 | "name": "stdout",
684 | "output_type": "stream",
685 | "text": [
686 | "b'\\x00\\x01'\n",
687 | "\n"
688 | ]
689 | }
690 | ],
691 | "source": [
692 | "variable_byte = variable.to_bytes(2, byteorder = 'big')\n",
693 | "print(variable_byte)\n",
694 | "print(type(variable_byte))"
695 | ]
696 | },
697 | {
698 | "cell_type": "markdown",
699 | "id": "7e65e272",
700 | "metadata": {},
701 | "source": [
702 | "### 1.3.3.2 重识常量"
703 | ]
704 | },
705 | {
706 | "cell_type": "markdown",
707 | "id": "15c1784c",
708 | "metadata": {},
709 | "source": [
710 | "Python 中的常量也是对象,其中最常用到对象方法的是字符串常量。\n",
711 | "\n",
712 | "字符串常用方法如下:\n",
713 | "- `format()`: 用于从其他信息中构造字符串。\n",
714 | "- `replace()`: 用于替代字符串中的某个字符或子串。\n",
715 | "- `split()`: 用于通过某种字符分隔字符串。\n",
716 | "- `upper()`: 把字符串转换成大写。\n",
717 | "- `lower()`: 把字符串转化成小写。"
718 | ]
719 | },
720 | {
721 | "cell_type": "code",
722 | "execution_count": 16,
723 | "id": "c94eed80",
724 | "metadata": {},
725 | "outputs": [
726 | {
727 | "name": "stdout",
728 | "output_type": "stream",
729 | "text": [
730 | "Learn Python in a smart way!!\n",
731 | "Learn PHP in a hard way!!\n"
732 | ]
733 | }
734 | ],
735 | "source": [
736 | "## format 方法使用 {数字 i} 对应 (第i个变量) 来控制用于构造字符串的参数 \n",
737 | "print(\"Learn {0} in a {1} way!!\".format('Python','smart'))\n",
738 | "print(\"Learn {0} in a {1} way!!\".format('PHP','hard'))"
739 | ]
740 | },
741 | {
742 | "cell_type": "code",
743 | "execution_count": 17,
744 | "id": "ac2c2093",
745 | "metadata": {},
746 | "outputs": [
747 | {
748 | "name": "stdout",
749 | "output_type": "stream",
750 | "text": [
751 | "Learn Python in a hard way!!\n"
752 | ]
753 | }
754 | ],
755 | "source": [
756 | "## replace 方法使用一个或多个参数分隔字符串,并返回子串构成的序列\n",
757 | "print(\"Learn Python in a smart way!!\".replace('smart','hard'))"
758 | ]
759 | },
760 | {
761 | "cell_type": "code",
762 | "execution_count": 18,
763 | "id": "a05cff81",
764 | "metadata": {},
765 | "outputs": [
766 | {
767 | "name": "stdout",
768 | "output_type": "stream",
769 | "text": [
770 | "['Learn', 'Python', 'in', 'a', 'smart', 'way!!']\n"
771 | ]
772 | }
773 | ],
774 | "source": [
775 | "## split 方法使用一个或多个参数分隔字符串,并返回子串构成的序列\n",
776 | "print(\"Learn Python in a smart way!!\".split(' '))"
777 | ]
778 | },
779 | {
780 | "cell_type": "code",
781 | "execution_count": 19,
782 | "id": "3f916203",
783 | "metadata": {},
784 | "outputs": [
785 | {
786 | "name": "stdout",
787 | "output_type": "stream",
788 | "text": [
789 | "LEARN PYTHON IN A SMART WAY!!\n",
790 | "learn python in a smart way!!\n"
791 | ]
792 | }
793 | ],
794 | "source": [
795 | "## upper 和 lower 方法转化大小写\n",
796 | "print(\"Learn Python in a smart way!!\".upper())\n",
797 | "print(\"Learn Python in a smart way!!\".lower())"
798 | ]
799 | },
800 | {
801 | "cell_type": "markdown",
802 | "id": "devoted-cedar",
803 | "metadata": {},
804 | "source": [
805 | "### 1.3.3.2 重识函数"
806 | ]
807 | },
808 | {
809 | "cell_type": "markdown",
810 | "id": "pharmaceutical-district",
811 | "metadata": {},
812 | "source": [
813 | "更神奇的是,在 Python 中函数也是对象,因此函数也有自己的数据与方法。"
814 | ]
815 | },
816 | {
817 | "cell_type": "code",
818 | "execution_count": 20,
819 | "id": "killing-modern",
820 | "metadata": {},
821 | "outputs": [],
822 | "source": [
823 | "def check_sum(num1, num2, target):\n",
824 | " ## 在 def xxx(): 下面缩进的是函数的内容\n",
825 | " a = num1\n",
826 | " b = num2\n",
827 | " return a + b == target"
828 | ]
829 | },
830 | {
831 | "cell_type": "markdown",
832 | "id": "tight-generation",
833 | "metadata": {},
834 | "source": [
835 | "通过 `.__name__` 成员变量可以获得函数的名字:"
836 | ]
837 | },
838 | {
839 | "cell_type": "code",
840 | "execution_count": 21,
841 | "id": "extensive-firmware",
842 | "metadata": {},
843 | "outputs": [
844 | {
845 | "data": {
846 | "text/plain": [
847 | "'check_sum'"
848 | ]
849 | },
850 | "execution_count": 21,
851 | "metadata": {},
852 | "output_type": "execute_result"
853 | }
854 | ],
855 | "source": [
856 | "check_sum.__name__"
857 | ]
858 | },
859 | {
860 | "cell_type": "markdown",
861 | "id": "modern-sewing",
862 | "metadata": {},
863 | "source": [
864 | "### 1.3.3.3 重识数据结构"
865 | ]
866 | },
867 | {
868 | "cell_type": "markdown",
869 | "id": "willing-parks",
870 | "metadata": {},
871 | "source": [
872 | "现在你可以想象到,数据结构也理所应当是对象。是的,数据结构为我们提供了许多非常的方法!上一节中的 `append` 就是其中一个。"
873 | ]
874 | },
875 | {
876 | "cell_type": "code",
877 | "execution_count": 22,
878 | "id": "soviet-determination",
879 | "metadata": {},
880 | "outputs": [],
881 | "source": [
882 | "l = [1,2,3,4]"
883 | ]
884 | },
885 | {
886 | "cell_type": "code",
887 | "execution_count": 23,
888 | "id": "weighted-ordinance",
889 | "metadata": {},
890 | "outputs": [
891 | {
892 | "name": "stdout",
893 | "output_type": "stream",
894 | "text": [
895 | "[1, 2, 3, 4, 5]\n"
896 | ]
897 | }
898 | ],
899 | "source": [
900 | "l.append(5)\n",
901 | "print(l)"
902 | ]
903 | },
904 | {
905 | "cell_type": "markdown",
906 | "id": "conceptual-richardson",
907 | "metadata": {},
908 | "source": [
909 | "除此之外,我们可以通过 `pop` 方法替代 `del` 关键字删除序列内某个元素:"
910 | ]
911 | },
912 | {
913 | "cell_type": "code",
914 | "execution_count": 24,
915 | "id": "american-continent",
916 | "metadata": {},
917 | "outputs": [
918 | {
919 | "name": "stdout",
920 | "output_type": "stream",
921 | "text": [
922 | "[1, 3, 4, 5]\n"
923 | ]
924 | }
925 | ],
926 | "source": [
927 | "l.pop(1)\n",
928 | "print(l)"
929 | ]
930 | },
931 | {
932 | "cell_type": "markdown",
933 | "id": "broke-atmosphere",
934 | "metadata": {},
935 | "source": [
936 | "通过 `insert` 方法在特定位置增加元素:"
937 | ]
938 | },
939 | {
940 | "cell_type": "code",
941 | "execution_count": 25,
942 | "id": "metropolitan-conference",
943 | "metadata": {},
944 | "outputs": [
945 | {
946 | "name": "stdout",
947 | "output_type": "stream",
948 | "text": [
949 | "[1, 1, 3, 4, 5]\n"
950 | ]
951 | }
952 | ],
953 | "source": [
954 | "## 第一个参数是位置,第二个参数是插入的元素\n",
955 | "l.insert(0,1)\n",
956 | "print(l)"
957 | ]
958 | },
959 | {
960 | "cell_type": "markdown",
961 | "id": "corrected-seeking",
962 | "metadata": {},
963 | "source": [
964 | "同样的,在元组、字典、集合等数据结构中也提供了很多方法,在此将常用的方法总结如下:"
965 | ]
966 | },
967 | {
968 | "cell_type": "markdown",
969 | "id": "liberal-drive",
970 | "metadata": {},
971 | "source": [
972 | "- 列表\n",
973 | " - `append(x)` 把元素 x 放在入列表尾部\n",
974 | " - `count(x)` 统计元素 x 在列表中出现次数\n",
975 | " - `extent(seq)` 把新列表 seq 合并到列表尾部\n",
976 | " - `index(x)` 返回元素 x 在列表第一次出现的位置\n",
977 | " - `insert(index, x)` 把元素 x 插入到 index 位置\n",
978 | " - `pop(index)` 删除并返回 index 所在位置的元素\n",
979 | " - `remove(x)` 删除出现的第一个 x 元素\n",
980 | " - `reverse()` 颠倒列表顺序\n",
981 | " - `sort()` 对列表进行排序\n",
982 | " \n",
983 | " \n",
984 | "- 字典\n",
985 | " - `clear()` 清除字典内所有元素\n",
986 | " - `copy()` 返回字典的一个复制\n",
987 | " - `has_key(key)` 检查 key 是否在字典中 \n",
988 | " - `items()` 返回一个含由 (key, value) 格式元组构成的列表\n",
989 | " - `keys()` 返回由键构成列表\n",
990 | " - `values()` 返回由值构成的列表\n",
991 | " - `setdefault(key, default)` 为键 key 添加默认值 default\n",
992 | " - `pop(key)` 删除 key 并返回对应的值\n",
993 | " \n",
994 | " \n",
995 | "- 集合\n",
996 | " - `add(x)` 向集合中添加元素 x\n",
997 | " - `clear()` 清空集合\n",
998 | " - `copy()` 返回集合的一个复制\n",
999 | " - `difference(set)` 返回集合与另一个集合的差集 \n",
1000 | " - `discard(x)` 删除元素 x \n",
1001 | " - `isdisjoint(set)` 判断两个集合是否有交集 \n",
1002 | " - `issubset(set)` 判断新集合 set 是否是集合的子集\n",
1003 | " - `issuperset()` 判断新集合 set 是否是集合的超集"
1004 | ]
1005 | },
1006 | {
1007 | "cell_type": "markdown",
1008 | "id": "massive-selection",
1009 | "metadata": {},
1010 | "source": [
1011 | "### 1.3.3.4 重识程序"
1012 | ]
1013 | },
1014 | {
1015 | "cell_type": "markdown",
1016 | "id": "departmental-major",
1017 | "metadata": {},
1018 | "source": [
1019 | "在某种意义上,我们也可以认为 Python 程序是一个对象,它也有自己的数据和方法。其中 `__name__` 就是它的一个变量,我们并没有定义过这个变量,但由于它是程序的对象变量,因此可以直接调用。"
1020 | ]
1021 | },
1022 | {
1023 | "cell_type": "code",
1024 | "execution_count": 26,
1025 | "id": "regulated-speed",
1026 | "metadata": {},
1027 | "outputs": [
1028 | {
1029 | "data": {
1030 | "text/plain": [
1031 | "'__main__'"
1032 | ]
1033 | },
1034 | "execution_count": 26,
1035 | "metadata": {},
1036 | "output_type": "execute_result"
1037 | }
1038 | ],
1039 | "source": [
1040 | "__name__\n"
1041 | ]
1042 | },
1043 | {
1044 | "cell_type": "markdown",
1045 | "id": "characteristic-persian",
1046 | "metadata": {},
1047 | "source": [
1048 | "## 1.3.4 练习"
1049 | ]
1050 | },
1051 | {
1052 | "cell_type": "markdown",
1053 | "id": "engaged-ribbon",
1054 | "metadata": {},
1055 | "source": [
1056 | "### 1.3.4.1 重构成绩管理系统\n",
1057 | "\n",
1058 | "\n",
1059 | "\n",
1060 | " \n",
1061 | "此练习是开放题,使用 面向对象 的编程方法重构之前的成绩管理系统,并完成之前的任务。\n",
1062 | "\n",
1063 | "Task 1. 在上一次期末考试中,XiaoHu 考了数学 65 分,语文 55 分;XiaoMing 考了数学 80 分,语文92 分;XiaoWei 考了数学 95 分,语文 98 分,以此建立学生成绩管理系统。\n",
1064 | "\n",
1065 | "Task 2. 在本次期末考试中,XiaoHu 考了数学 95 分,语文 85 分;XiaoMing 考了数学 75 分,语文 71 分;XiaoWei 考了数学 92 分,语文 93 分,以此对之前的成绩进行更新。\n",
1066 | "\n",
1067 | "Task 3. 由于 XiaoMing 的成绩出现了大幅度下滑,家长决定要 XiaoMing 转学到另一所高中,以此在系统中删除 XiaoMing 的信息。\n",
1068 | "\n",
1069 | "Task 4. 学校新转来的学生 Cryin 本次考试成绩为 数学 87 分,语文 88 分,在系统中录入 Cryin 的成绩。\n",
1070 | "\n",
1071 | " "
1072 | ]
1073 | },
1074 | {
1075 | "cell_type": "code",
1076 | "execution_count": 27,
1077 | "id": "direct-stick",
1078 | "metadata": {},
1079 | "outputs": [],
1080 | "source": [
1081 | "class student():\n",
1082 | " def __init__(self, name, Math_score, Chinese_score):\n",
1083 | " self.name = name\n",
1084 | " self.Math_score = Math_score\n",
1085 | " self.Chinese_score = Chinese_score\n",
1086 | " \n",
1087 | " ## repr 函数用于定义对象被输出时的输出结果\n",
1088 | " def __repr__(self):\n",
1089 | " return str((self.name, self.Math_score, self.Chinese_score))\n",
1090 | " \n",
1091 | " def change_score(self, course_name, score):\n",
1092 | " if course_name == 'Math':\n",
1093 | " self.Math_score = score\n",
1094 | " elif course_name == 'Chinese':\n",
1095 | " self.Chinese_score = score\n",
1096 | " else:\n",
1097 | " print(course_name, \" course is still not in current system\")\n",
1098 | " \n",
1099 | " def print_name(self,):\n",
1100 | " print(self.name)\n",
1101 | " \n",
1102 | " name = 'Undefined'\n",
1103 | " Math_score = None\n",
1104 | " Chinese_score = None"
1105 | ]
1106 | },
1107 | {
1108 | "cell_type": "markdown",
1109 | "id": "solid-sequence",
1110 | "metadata": {},
1111 | "source": [
1112 | "之前我们实现了学生类,现在我们通过把学生对象保存在字典中实现一个成绩系统。"
1113 | ]
1114 | },
1115 | {
1116 | "cell_type": "code",
1117 | "execution_count": 28,
1118 | "id": "available-exhibition",
1119 | "metadata": {},
1120 | "outputs": [
1121 | {
1122 | "name": "stdout",
1123 | "output_type": "stream",
1124 | "text": [
1125 | "{'XiaoHu': ('XiaoHu', 65, 55), 'XiaoMing': ('XiaoMing', 80, 92), 'XiaoWei': ('XiaoHu', 95, 98)}\n",
1126 | "{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoMing': ('XiaoMing', 75, 71), 'XiaoWei': ('XiaoHu', 92, 93)}\n",
1127 | "{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoWei': ('XiaoHu', 92, 93)}\n",
1128 | "{'XiaoHu': ('XiaoHu', 95, 85), 'XiaoWei': ('XiaoHu', 92, 93), 'Cryin': ('Cryin', 87, 88)}\n"
1129 | ]
1130 | }
1131 | ],
1132 | "source": [
1133 | "## Task1\n",
1134 | "ab = {}\n",
1135 | "ab.setdefault('XiaoHu', student('XiaoHu', 65, 55))\n",
1136 | "ab.setdefault('XiaoMing', student('XiaoMing', 80, 92))\n",
1137 | "ab.setdefault('XiaoWei', student('XiaoHu', 95, 98))\n",
1138 | "print(ab)\n",
1139 | "\n",
1140 | "## Task2\n",
1141 | "ab['XiaoHu'].change_score('Math', 95)\n",
1142 | "ab['XiaoMing'].change_score('Math', 75)\n",
1143 | "ab['XiaoWei'].change_score('Math', 92)\n",
1144 | "\n",
1145 | "ab['XiaoHu'].change_score('Chinese', 85)\n",
1146 | "ab['XiaoMing'].change_score('Chinese', 71)\n",
1147 | "ab['XiaoWei'].change_score('Chinese', 93)\n",
1148 | "print(ab)\n",
1149 | "\n",
1150 | "## Task3\n",
1151 | "ab.pop('XiaoMing')\n",
1152 | "print(ab)\n",
1153 | "\n",
1154 | "## Task4\n",
1155 | "ab.setdefault('Cryin', student('Cryin', 87, 88))\n",
1156 | "print(ab)"
1157 | ]
1158 | }
1159 | ],
1160 | "metadata": {
1161 | "kernelspec": {
1162 | "display_name": "Python 3.9.7 ('base')",
1163 | "language": "python",
1164 | "name": "python3"
1165 | },
1166 | "language_info": {
1167 | "codemirror_mode": {
1168 | "name": "ipython",
1169 | "version": 3
1170 | },
1171 | "file_extension": ".py",
1172 | "mimetype": "text/x-python",
1173 | "name": "python",
1174 | "nbconvert_exporter": "python",
1175 | "pygments_lexer": "ipython3",
1176 | "version": "3.9.7"
1177 | },
1178 | "toc": {
1179 | "base_numbering": 1,
1180 | "nav_menu": {},
1181 | "number_sections": false,
1182 | "sideBar": true,
1183 | "skip_h1_title": true,
1184 | "title_cell": "Table of Contents",
1185 | "title_sidebar": "Contents",
1186 | "toc_cell": false,
1187 | "toc_position": {
1188 | "height": "calc(100% - 180px)",
1189 | "left": "10px",
1190 | "top": "150px",
1191 | "width": "218.55978393554688px"
1192 | },
1193 | "toc_section_display": true,
1194 | "toc_window_display": true
1195 | },
1196 | "vscode": {
1197 | "interpreter": {
1198 | "hash": "c6e4e9f98eb68ad3b7c296f83d20e6de614cb42e90992a65aa266555a3137d0d"
1199 | }
1200 | }
1201 | },
1202 | "nbformat": 4,
1203 | "nbformat_minor": 5
1204 | }
1205 |
--------------------------------------------------------------------------------
/4. Python 文件与模块.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "a870e71d",
6 | "metadata": {},
7 | "source": [
8 | "# Python 文件与模块"
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "id": "1257bf93",
14 | "metadata": {},
15 | "source": [
16 | "## 1.4.1 文件"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "id": "77a65ea6",
22 | "metadata": {},
23 | "source": [
24 | "经过几百万年的演化,人类进化出了其他动物没有的“长期记忆”,进而拥有了语言、文化甚至发展出文明,走上了一条未曾设想的道路。在人类大脑中,“短期记忆”由海马体负责,“长期记忆”则由大脑皮层中的额叶负责;在计算机中也同样存在长短期记忆,短期记忆由程序中的变量负责,长期记忆则交给电脑中的文件系统。"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "id": "8199ed32",
30 | "metadata": {},
31 | "source": [
32 | "### 1.4.1.1 Open 函数"
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "id": "6638d46b",
38 | "metadata": {},
39 | "source": [
40 | "Python `open( )` 函数用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数。"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "id": "508c28c5",
46 | "metadata": {},
47 | "source": [
48 | "> 为了测试 Python 中的文件操作,我们先通过命令行在当前目录保存一个内容为 “hello world!” 的 test.txt 文件。\n",
49 | "\n",
50 | "- Mac / Linux: `echo Hello world >> test.txt`\n",
51 | "- Windows: `echo Hello world > test.txt`\n",
52 | "\n",
53 | " "
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "id": "fd7d8214",
59 | "metadata": {},
60 | "source": [
61 | "`open(file, mode)` 函数主要有 file 和 mode 两个参数,其中 file 为需要读写文件的路径。mode 为读取文件时的模式,常用的模式有以下几个:\n",
62 | "\n",
63 | "- r:以字符串的形式读取文件。\n",
64 | "- rb:以二进制的形式读取文件。\n",
65 | "- w:写入文件。\n",
66 | "- a:追加写入文件。\n",
67 | "\n",
68 | "不同模式下返回的文件对象功能也会不同。"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": 3,
74 | "id": "85581df5",
75 | "metadata": {},
76 | "outputs": [
77 | {
78 | "name": "stdout",
79 | "output_type": "stream",
80 | "text": [
81 | "\n"
82 | ]
83 | }
84 | ],
85 | "source": [
86 | "file = open('test.txt', 'r')\n",
87 | "print(type(file))"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "id": "d4297989",
93 | "metadata": {},
94 | "source": [
95 | "### 1.4.1.2 文件对象"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "id": "b2665bee",
101 | "metadata": {},
102 | "source": [
103 | "`open` 函数会返回一个 文件对象。在进行文件操作前,我们首先需要了解文件对象提供了哪些常用的方法:\n",
104 | "\n",
105 | "- `close( )`: 关闭文件\n",
106 | "- 在 r 与 rb 模式下:\n",
107 | " - `read()`: 读取整个文件\n",
108 | " - `readline()`: 读取文件的一行\n",
109 | " - `readlines()`: 读取文件的所有行\n",
110 | "- 在 w 与 a 模式下:\n",
111 | " - `write()`: \n",
112 | " - `writelines()`: "
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "id": "0660d622",
118 | "metadata": {},
119 | "source": [
120 | "下面我们通过实例学习这几种方法:"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 4,
126 | "id": "c42d7de4",
127 | "metadata": {},
128 | "outputs": [
129 | {
130 | "name": "stdout",
131 | "output_type": "stream",
132 | "text": [
133 | "hello world\n",
134 | "\n"
135 | ]
136 | }
137 | ],
138 | "source": [
139 | "## 通过 read 方法读取整个文件\n",
140 | "content = file.read()\n",
141 | "print(content)"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": 5,
147 | "id": "0604c0d2",
148 | "metadata": {},
149 | "outputs": [
150 | {
151 | "name": "stdout",
152 | "output_type": "stream",
153 | "text": [
154 | "\n"
155 | ]
156 | }
157 | ],
158 | "source": [
159 | "## 通过 readline() 读取文件的一行\n",
160 | "content = file.readline()\n",
161 | "print(content)"
162 | ]
163 | },
164 | {
165 | "cell_type": "markdown",
166 | "id": "921fae61",
167 | "metadata": {},
168 | "source": [
169 | "我们发现上面的代码竟然什么也没输出,这是为什么?\n",
170 | "\n",
171 | "你可以理解 open 函数返回的是一个指针,类似于你在 Microsolf Word 文档里编辑文档时闪烁的光标。在执行过 `file.read( )` 操作后,由于读取了整个文件,这个指针已经来到了文件末尾,因此 `file.readline( )` 没有获取到文件的内容。这种情况我们可以通过 close 方法关闭文件后再重新打开。"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": 6,
177 | "id": "7d180532",
178 | "metadata": {},
179 | "outputs": [
180 | {
181 | "name": "stdout",
182 | "output_type": "stream",
183 | "text": [
184 | "hello world\n",
185 | "\n"
186 | ]
187 | }
188 | ],
189 | "source": [
190 | "## 关闭之前打开的 test.txt 文件\n",
191 | "file.close()\n",
192 | "## 重新打开\n",
193 | "file = open('test.txt', 'r')\n",
194 | "content = file.readline()\n",
195 | "print(content)"
196 | ]
197 | },
198 | {
199 | "cell_type": "markdown",
200 | "id": "1ebaed11",
201 | "metadata": {},
202 | "source": [
203 | "因此在操作文件时,我们一定要注意每次操作结束后,及时通过 `close( )` 方法关闭文件。"
204 | ]
205 | },
206 | {
207 | "cell_type": "code",
208 | "execution_count": 7,
209 | "id": "8388fe2d",
210 | "metadata": {},
211 | "outputs": [],
212 | "source": [
213 | "## 以 w 模式打开文件test.txt\n",
214 | "file = open('test.txt', 'w')\n",
215 | "## 创建需要写入的字符串变量 在字符串中 \\n 代表换行(也就是回车)\n",
216 | "content = 'Hello world!\\nHello Python!!\\n'\n",
217 | "## 写入到 test.txt 文件中\n",
218 | "file.write(content)\n",
219 | "## 关闭文件对象\n",
220 | "file.close()"
221 | ]
222 | },
223 | {
224 | "cell_type": "markdown",
225 | "id": "a4726843",
226 | "metadata": {},
227 | "source": [
228 | " "
229 | ]
230 | },
231 | {
232 | "cell_type": "markdown",
233 | "id": "4db4bd05",
234 | "metadata": {},
235 | "source": [
236 | "需要注意在上述操作中,w 模式会覆盖之前的文件。如果你想在文件后面追加内容,可以使用 a 模式操作。"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": 8,
242 | "id": "f3352cfd",
243 | "metadata": {},
244 | "outputs": [],
245 | "source": [
246 | "## 以 w 模式打开文件test.txt\n",
247 | "file = open('test.txt', 'a')\n",
248 | "## 创建需要追加的字符串变量\n",
249 | "content = 'Hello smart way!!!'\n",
250 | "## 写入到 test.txt 文件中\n",
251 | "file.write(content)\n",
252 | "## 关闭文件对象\n",
253 | "file.close()"
254 | ]
255 | },
256 | {
257 | "cell_type": "markdown",
258 | "id": "01915069",
259 | "metadata": {},
260 | "source": [
261 | " "
262 | ]
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "id": "4d487fad",
267 | "metadata": {},
268 | "source": [
269 | "## 1.4.2 模块"
270 | ]
271 | },
272 | {
273 | "cell_type": "markdown",
274 | "id": "a8bab259",
275 | "metadata": {},
276 | "source": [
277 | "在普罗米修斯为人类带来火种后,人类制造出了各种各样的工具。工具的产生大大提高了人类的生产力,使人类从石器时代步入铁器时代、蒸汽时代以及现在的信息时代。\n",
278 | "\n",
279 | "在之前的学习中,为了更简洁高效地完成任务,我们引入了函数、数据结构以及面向对象编程等工具。但每次我们在这个代码写完后,在下一个代码中只能把代码复制粘贴过去,而模块可以帮助我们把一个代码添加到另一个代码中,真正实现了工具等复用性。"
280 | ]
281 | },
282 | {
283 | "cell_type": "markdown",
284 | "id": "ac5aa0a2",
285 | "metadata": {},
286 | "source": [
287 | "编写模块的方式有很多,其中最简单的模块就是创建一个包含很多函数、变量以及类并以 .py 为后缀的文件。下面我们把上一节中实现的 class 类保存在 student.py 文件中:"
288 | ]
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "id": "46b45d90",
293 | "metadata": {},
294 | "source": [
295 | " "
296 | ]
297 | },
298 | {
299 | "cell_type": "markdown",
300 | "id": "575e38db",
301 | "metadata": {},
302 | "source": [
303 | "> 为了方便读者,也可使用下面的代码来直接在当前目录生成 `student.py` 文件。"
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": 9,
309 | "id": "bc4a2658",
310 | "metadata": {},
311 | "outputs": [],
312 | "source": [
313 | "file = open('student.py', 'w',encoding=\"utf-8\")\n",
314 | "file.write(\"\"\"class student():\n",
315 | " def __init__(self, name, Math_score, Chinese_score):\n",
316 | " self.name = name\n",
317 | " self.Math_score = Math_score\n",
318 | " self.Chinese_score = Chinese_score\n",
319 | " \n",
320 | " ## repr 函数用于定义对象被输出时的输出结果\n",
321 | " def __repr__(self):\n",
322 | " return str((self.name, self.Math_score, self.Chinese_score))\n",
323 | " \n",
324 | " def change_score(self, course_name, score):\n",
325 | " if course_name == 'Math':\n",
326 | " self.Math_score = score\n",
327 | " elif course_name == 'Chinese':\n",
328 | " self.Chinese_score = score\n",
329 | " else:\n",
330 | " print(course_name, \" course is still not in current system\")\n",
331 | " \n",
332 | " def print_name(self,):\n",
333 | " print(self.name)\n",
334 | " \n",
335 | " name = 'Undefined'\n",
336 | " Math_score = None\n",
337 | " Chinese_score = None\"\"\")\n",
338 | "file.close()"
339 | ]
340 | },
341 | {
342 | "cell_type": "markdown",
343 | "id": "ef0e6af7",
344 | "metadata": {},
345 | "source": [
346 | "使用 `import` 关键字可以把一个模块引入到一个程序来使用它的功能。记得在上一节中我们说过一个程序也可以是一个对象,这时 student.py 程序就成了一个对象,而里面的 student 类便成了它的对象变量。"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": 10,
352 | "id": "8de02c29",
353 | "metadata": {},
354 | "outputs": [],
355 | "source": [
356 | "import student"
357 | ]
358 | },
359 | {
360 | "cell_type": "code",
361 | "execution_count": 11,
362 | "id": "4c9f7a60",
363 | "metadata": {},
364 | "outputs": [
365 | {
366 | "name": "stdout",
367 | "output_type": "stream",
368 | "text": [
369 | "('XiaoHu', 65, 55)\n"
370 | ]
371 | }
372 | ],
373 | "source": [
374 | "xiaohu = student.student('XiaoHu', 65, 55)\n",
375 | "print(xiaohu)"
376 | ]
377 | },
378 | {
379 | "cell_type": "markdown",
380 | "id": "2b91e95f",
381 | "metadata": {},
382 | "source": [
383 | "通过 student.py 这个模块,我们不需要重复编写就可以在任何程序中使用 student 类!正是因为有了模块,才使得数据科学中复杂的算法与模型可以封装到模块中,用户只需要使用模块中定义好的函数与类。"
384 | ]
385 | },
386 | {
387 | "cell_type": "markdown",
388 | "id": "c422e8ea",
389 | "metadata": {},
390 | "source": [
391 | "当我们只需要模块中的几个函数或类时,也可以采用 `from model_name import xxx` 的写法导入指定部分:"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": 12,
397 | "id": "abf9e578",
398 | "metadata": {},
399 | "outputs": [
400 | {
401 | "name": "stdout",
402 | "output_type": "stream",
403 | "text": [
404 | "('XiaoHu', 65, 55)\n"
405 | ]
406 | }
407 | ],
408 | "source": [
409 | "## 仅导入 student 类\n",
410 | "from student import student\n",
411 | "## 这时直接通过类名,不需要使用模块名\n",
412 | "xiaohu = student('XiaoHu', 65, 55)\n",
413 | "print(xiaohu)"
414 | ]
415 | },
416 | {
417 | "cell_type": "markdown",
418 | "id": "3024271d",
419 | "metadata": {},
420 | "source": [
421 | "在 Python 中内置了很多标准模块,例如用于数学操作的 math 模块与处理时间的 time 模块:"
422 | ]
423 | },
424 | {
425 | "cell_type": "code",
426 | "execution_count": 13,
427 | "id": "323741ef",
428 | "metadata": {},
429 | "outputs": [
430 | {
431 | "name": "stdout",
432 | "output_type": "stream",
433 | "text": [
434 | "4.174387269895637\n"
435 | ]
436 | }
437 | ],
438 | "source": [
439 | "import math\n",
440 | "## 通过 math.log 计算数值的对数\n",
441 | "print(math.log(xiaohu.Math_score))"
442 | ]
443 | },
444 | {
445 | "cell_type": "code",
446 | "execution_count": 14,
447 | "id": "67f56bad",
448 | "metadata": {},
449 | "outputs": [
450 | {
451 | "name": "stdout",
452 | "output_type": "stream",
453 | "text": [
454 | "Tue Jul 12 21:37:51 2022\n"
455 | ]
456 | }
457 | ],
458 | "source": [
459 | "import time\n",
460 | "## 通过 time 库中多个方法获取当前时间\n",
461 | "## time.time 获取当前时间的 unix 时间戳\n",
462 | "## time.loacltime 把当前时间的 unix 时间戳按照时区划分\n",
463 | "## time.asctime 把按时区划分的时间戳转化成标准日期格式\n",
464 | "print(time.asctime(time.localtime(time.time())))"
465 | ]
466 | },
467 | {
468 | "cell_type": "markdown",
469 | "id": "389616ba",
470 | "metadata": {},
471 | "source": [
472 | "除此之外,Python 还有很多标准库值得我们去探索。例如 re 库可以实现字符串正则表达式的匹配,random 用来生成随机数,urllib 用来访问互联网……"
473 | ]
474 | },
475 | {
476 | "cell_type": "markdown",
477 | "id": "77869207",
478 | "metadata": {},
479 | "source": [
480 | "## 1.4.3 练习"
481 | ]
482 | },
483 | {
484 | "cell_type": "markdown",
485 | "id": "709140e5",
486 | "metadata": {},
487 | "source": [
488 | "### 1.4.3.1 学生信息本地存储"
489 | ]
490 | },
491 | {
492 | "cell_type": "markdown",
493 | "id": "2d0897a3",
494 | "metadata": {},
495 | "source": [
496 | "> 之前我们实现了学生信息的“增删查改”功能,现在希望通过文件系统保存学生的信息,每次打开程序时可以载入,关闭程序时可以保存。"
497 | ]
498 | },
499 | {
500 | "cell_type": "markdown",
501 | "id": "f0673d08",
502 | "metadata": {},
503 | "source": [
504 | "### 1.4.3.2 Python 之禅"
505 | ]
506 | },
507 | {
508 | "cell_type": "markdown",
509 | "id": "7d95cc3f",
510 | "metadata": {},
511 | "source": [
512 | "\n",
513 | "\n",
514 | "首先在这里恭喜各位同学完成了 Python 的全部学习内容!在这四章中希望你可以体会到本教程简洁明快的风格,这种风格与 Python 本身的代码设计风格是一致的。在 Tim Peters 编写的 “Python 之禅” 中的核心指导原则就是 “Simple is better than complex”。\n",
515 | "\n",
516 | "纵观历史,你会看到苹果创始人史蒂夫·乔布斯对 Less is More 的追求,看到无印良品“删繁就简,去其浮华”的核心设计理念,看到山下英子在《断舍离》中对生活做减法的观点,甚至看到苏东坡“竹杖芒鞋轻胜马,一蓑烟雨任平生”的人生态度。你会发现极简主义不只存在于 Python 编程中,它本就是这个世界优雅的一条运行法则。\n",
517 | " \n",
518 | "本练习让我们导入 this 模块,用心体会一下 Python 的设计原则。\n",
519 | " \n",
520 | " "
521 | ]
522 | },
523 | {
524 | "cell_type": "code",
525 | "execution_count": 15,
526 | "id": "d918ee0e",
527 | "metadata": {
528 | "scrolled": false
529 | },
530 | "outputs": [
531 | {
532 | "name": "stdout",
533 | "output_type": "stream",
534 | "text": [
535 | "The Zen of Python, by Tim Peters\n",
536 | "\n",
537 | "Beautiful is better than ugly.\n",
538 | "Explicit is better than implicit.\n",
539 | "Simple is better than complex.\n",
540 | "Complex is better than complicated.\n",
541 | "Flat is better than nested.\n",
542 | "Sparse is better than dense.\n",
543 | "Readability counts.\n",
544 | "Special cases aren't special enough to break the rules.\n",
545 | "Although practicality beats purity.\n",
546 | "Errors should never pass silently.\n",
547 | "Unless explicitly silenced.\n",
548 | "In the face of ambiguity, refuse the temptation to guess.\n",
549 | "There should be one-- and preferably only one --obvious way to do it.\n",
550 | "Although that way may not be obvious at first unless you're Dutch.\n",
551 | "Now is better than never.\n",
552 | "Although never is often better than *right* now.\n",
553 | "If the implementation is hard to explain, it's a bad idea.\n",
554 | "If the implementation is easy to explain, it may be a good idea.\n",
555 | "Namespaces are one honking great idea -- let's do more of those!\n"
556 | ]
557 | }
558 | ],
559 | "source": [
560 | "import this"
561 | ]
562 | }
563 | ],
564 | "metadata": {
565 | "kernelspec": {
566 | "display_name": "Python 3.9.7 ('base')",
567 | "language": "python",
568 | "name": "python3"
569 | },
570 | "language_info": {
571 | "codemirror_mode": {
572 | "name": "ipython",
573 | "version": 3
574 | },
575 | "file_extension": ".py",
576 | "mimetype": "text/x-python",
577 | "name": "python",
578 | "nbconvert_exporter": "python",
579 | "pygments_lexer": "ipython3",
580 | "version": "3.9.7"
581 | },
582 | "toc": {
583 | "base_numbering": 1,
584 | "nav_menu": {},
585 | "number_sections": false,
586 | "sideBar": true,
587 | "skip_h1_title": false,
588 | "title_cell": "Table of Contents",
589 | "title_sidebar": "Contents",
590 | "toc_cell": false,
591 | "toc_position": {},
592 | "toc_section_display": true,
593 | "toc_window_display": true
594 | },
595 | "vscode": {
596 | "interpreter": {
597 | "hash": "c6e4e9f98eb68ad3b7c296f83d20e6de614cb42e90992a65aa266555a3137d0d"
598 | }
599 | }
600 | },
601 | "nbformat": 4,
602 | "nbformat_minor": 5
603 | }
604 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution-NonCommercial-ShareAlike 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
58 | Public License
59 |
60 | By exercising the Licensed Rights (defined below), You accept and agree
61 | to be bound by the terms and conditions of this Creative Commons
62 | Attribution-NonCommercial-ShareAlike 4.0 International Public License
63 | ("Public License"). To the extent this Public License may be
64 | interpreted as a contract, You are granted the Licensed Rights in
65 | consideration of Your acceptance of these terms and conditions, and the
66 | Licensor grants You such rights in consideration of benefits the
67 | Licensor receives from making the Licensed Material available under
68 | these terms and conditions.
69 |
70 |
71 | Section 1 -- Definitions.
72 |
73 | a. Adapted Material means material subject to Copyright and Similar
74 | Rights that is derived from or based upon the Licensed Material
75 | and in which the Licensed Material is translated, altered,
76 | arranged, transformed, or otherwise modified in a manner requiring
77 | permission under the Copyright and Similar Rights held by the
78 | Licensor. For purposes of this Public License, where the Licensed
79 | Material is a musical work, performance, or sound recording,
80 | Adapted Material is always produced where the Licensed Material is
81 | synched in timed relation with a moving image.
82 |
83 | b. Adapter's License means the license You apply to Your Copyright
84 | and Similar Rights in Your contributions to Adapted Material in
85 | accordance with the terms and conditions of this Public License.
86 |
87 | c. BY-NC-SA Compatible License means a license listed at
88 | creativecommons.org/compatiblelicenses, approved by Creative
89 | Commons as essentially the equivalent of this Public License.
90 |
91 | d. Copyright and Similar Rights means copyright and/or similar rights
92 | closely related to copyright including, without limitation,
93 | performance, broadcast, sound recording, and Sui Generis Database
94 | Rights, without regard to how the rights are labeled or
95 | categorized. For purposes of this Public License, the rights
96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
97 | Rights.
98 |
99 | e. Effective Technological Measures means those measures that, in the
100 | absence of proper authority, may not be circumvented under laws
101 | fulfilling obligations under Article 11 of the WIPO Copyright
102 | Treaty adopted on December 20, 1996, and/or similar international
103 | agreements.
104 |
105 | f. Exceptions and Limitations means fair use, fair dealing, and/or
106 | any other exception or limitation to Copyright and Similar Rights
107 | that applies to Your use of the Licensed Material.
108 |
109 | g. License Elements means the license attributes listed in the name
110 | of a Creative Commons Public License. The License Elements of this
111 | Public License are Attribution, NonCommercial, and ShareAlike.
112 |
113 | h. Licensed Material means the artistic or literary work, database,
114 | or other material to which the Licensor applied this Public
115 | License.
116 |
117 | i. Licensed Rights means the rights granted to You subject to the
118 | terms and conditions of this Public License, which are limited to
119 | all Copyright and Similar Rights that apply to Your use of the
120 | Licensed Material and that the Licensor has authority to license.
121 |
122 | j. Licensor means the individual(s) or entity(ies) granting rights
123 | under this Public License.
124 |
125 | k. NonCommercial means not primarily intended for or directed towards
126 | commercial advantage or monetary compensation. For purposes of
127 | this Public License, the exchange of the Licensed Material for
128 | other material subject to Copyright and Similar Rights by digital
129 | file-sharing or similar means is NonCommercial provided there is
130 | no payment of monetary compensation in connection with the
131 | exchange.
132 |
133 | l. Share means to provide material to the public by any means or
134 | process that requires permission under the Licensed Rights, such
135 | as reproduction, public display, public performance, distribution,
136 | dissemination, communication, or importation, and to make material
137 | available to the public including in ways that members of the
138 | public may access the material from a place and at a time
139 | individually chosen by them.
140 |
141 | m. Sui Generis Database Rights means rights other than copyright
142 | resulting from Directive 96/9/EC of the European Parliament and of
143 | the Council of 11 March 1996 on the legal protection of databases,
144 | as amended and/or succeeded, as well as other essentially
145 | equivalent rights anywhere in the world.
146 |
147 | n. You means the individual or entity exercising the Licensed Rights
148 | under this Public License. Your has a corresponding meaning.
149 |
150 |
151 | Section 2 -- Scope.
152 |
153 | a. License grant.
154 |
155 | 1. Subject to the terms and conditions of this Public License,
156 | the Licensor hereby grants You a worldwide, royalty-free,
157 | non-sublicensable, non-exclusive, irrevocable license to
158 | exercise the Licensed Rights in the Licensed Material to:
159 |
160 | a. reproduce and Share the Licensed Material, in whole or
161 | in part, for NonCommercial purposes only; and
162 |
163 | b. produce, reproduce, and Share Adapted Material for
164 | NonCommercial purposes only.
165 |
166 | 2. Exceptions and Limitations. For the avoidance of doubt, where
167 | Exceptions and Limitations apply to Your use, this Public
168 | License does not apply, and You do not need to comply with
169 | its terms and conditions.
170 |
171 | 3. Term. The term of this Public License is specified in Section
172 | 6(a).
173 |
174 | 4. Media and formats; technical modifications allowed. The
175 | Licensor authorizes You to exercise the Licensed Rights in
176 | all media and formats whether now known or hereafter created,
177 | and to make technical modifications necessary to do so. The
178 | Licensor waives and/or agrees not to assert any right or
179 | authority to forbid You from making technical modifications
180 | necessary to exercise the Licensed Rights, including
181 | technical modifications necessary to circumvent Effective
182 | Technological Measures. For purposes of this Public License,
183 | simply making modifications authorized by this Section 2(a)
184 | (4) never produces Adapted Material.
185 |
186 | 5. Downstream recipients.
187 |
188 | a. Offer from the Licensor -- Licensed Material. Every
189 | recipient of the Licensed Material automatically
190 | receives an offer from the Licensor to exercise the
191 | Licensed Rights under the terms and conditions of this
192 | Public License.
193 |
194 | b. Additional offer from the Licensor -- Adapted Material.
195 | Every recipient of Adapted Material from You
196 | automatically receives an offer from the Licensor to
197 | exercise the Licensed Rights in the Adapted Material
198 | under the conditions of the Adapter's License You apply.
199 |
200 | c. No downstream restrictions. You may not offer or impose
201 | any additional or different terms or conditions on, or
202 | apply any Effective Technological Measures to, the
203 | Licensed Material if doing so restricts exercise of the
204 | Licensed Rights by any recipient of the Licensed
205 | Material.
206 |
207 | 6. No endorsement. Nothing in this Public License constitutes or
208 | may be construed as permission to assert or imply that You
209 | are, or that Your use of the Licensed Material is, connected
210 | with, or sponsored, endorsed, or granted official status by,
211 | the Licensor or others designated to receive attribution as
212 | provided in Section 3(a)(1)(A)(i).
213 |
214 | b. Other rights.
215 |
216 | 1. Moral rights, such as the right of integrity, are not
217 | licensed under this Public License, nor are publicity,
218 | privacy, and/or other similar personality rights; however, to
219 | the extent possible, the Licensor waives and/or agrees not to
220 | assert any such rights held by the Licensor to the limited
221 | extent necessary to allow You to exercise the Licensed
222 | Rights, but not otherwise.
223 |
224 | 2. Patent and trademark rights are not licensed under this
225 | Public License.
226 |
227 | 3. To the extent possible, the Licensor waives any right to
228 | collect royalties from You for the exercise of the Licensed
229 | Rights, whether directly or through a collecting society
230 | under any voluntary or waivable statutory or compulsory
231 | licensing scheme. In all other cases the Licensor expressly
232 | reserves any right to collect such royalties, including when
233 | the Licensed Material is used other than for NonCommercial
234 | purposes.
235 |
236 |
237 | Section 3 -- License Conditions.
238 |
239 | Your exercise of the Licensed Rights is expressly made subject to the
240 | following conditions.
241 |
242 | a. Attribution.
243 |
244 | 1. If You Share the Licensed Material (including in modified
245 | form), You must:
246 |
247 | a. retain the following if it is supplied by the Licensor
248 | with the Licensed Material:
249 |
250 | i. identification of the creator(s) of the Licensed
251 | Material and any others designated to receive
252 | attribution, in any reasonable manner requested by
253 | the Licensor (including by pseudonym if
254 | designated);
255 |
256 | ii. a copyright notice;
257 |
258 | iii. a notice that refers to this Public License;
259 |
260 | iv. a notice that refers to the disclaimer of
261 | warranties;
262 |
263 | v. a URI or hyperlink to the Licensed Material to the
264 | extent reasonably practicable;
265 |
266 | b. indicate if You modified the Licensed Material and
267 | retain an indication of any previous modifications; and
268 |
269 | c. indicate the Licensed Material is licensed under this
270 | Public License, and include the text of, or the URI or
271 | hyperlink to, this Public License.
272 |
273 | 2. You may satisfy the conditions in Section 3(a)(1) in any
274 | reasonable manner based on the medium, means, and context in
275 | which You Share the Licensed Material. For example, it may be
276 | reasonable to satisfy the conditions by providing a URI or
277 | hyperlink to a resource that includes the required
278 | information.
279 | 3. If requested by the Licensor, You must remove any of the
280 | information required by Section 3(a)(1)(A) to the extent
281 | reasonably practicable.
282 |
283 | b. ShareAlike.
284 |
285 | In addition to the conditions in Section 3(a), if You Share
286 | Adapted Material You produce, the following conditions also apply.
287 |
288 | 1. The Adapter's License You apply must be a Creative Commons
289 | license with the same License Elements, this version or
290 | later, or a BY-NC-SA Compatible License.
291 |
292 | 2. You must include the text of, or the URI or hyperlink to, the
293 | Adapter's License You apply. You may satisfy this condition
294 | in any reasonable manner based on the medium, means, and
295 | context in which You Share Adapted Material.
296 |
297 | 3. You may not offer or impose any additional or different terms
298 | or conditions on, or apply any Effective Technological
299 | Measures to, Adapted Material that restrict exercise of the
300 | rights granted under the Adapter's License You apply.
301 |
302 |
303 | Section 4 -- Sui Generis Database Rights.
304 |
305 | Where the Licensed Rights include Sui Generis Database Rights that
306 | apply to Your use of the Licensed Material:
307 |
308 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
309 | to extract, reuse, reproduce, and Share all or a substantial
310 | portion of the contents of the database for NonCommercial purposes
311 | only;
312 |
313 | b. if You include all or a substantial portion of the database
314 | contents in a database in which You have Sui Generis Database
315 | Rights, then the database in which You have Sui Generis Database
316 | Rights (but not its individual contents) is Adapted Material,
317 | including for purposes of Section 3(b); and
318 |
319 | c. You must comply with the conditions in Section 3(a) if You Share
320 | all or a substantial portion of the contents of the database.
321 |
322 | For the avoidance of doubt, this Section 4 supplements and does not
323 | replace Your obligations under this Public License where the Licensed
324 | Rights include other Copyright and Similar Rights.
325 |
326 |
327 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
328 |
329 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
330 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
331 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
332 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
333 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
334 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
335 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
336 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
337 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
338 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
339 |
340 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
341 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
342 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
343 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
344 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
345 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
346 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
347 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
348 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
349 |
350 | c. The disclaimer of warranties and limitation of liability provided
351 | above shall be interpreted in a manner that, to the extent
352 | possible, most closely approximates an absolute disclaimer and
353 | waiver of all liability.
354 |
355 |
356 | Section 6 -- Term and Termination.
357 |
358 | a. This Public License applies for the term of the Copyright and
359 | Similar Rights licensed here. However, if You fail to comply with
360 | this Public License, then Your rights under this Public License
361 | terminate automatically.
362 |
363 | b. Where Your right to use the Licensed Material has terminated under
364 | Section 6(a), it reinstates:
365 |
366 | 1. automatically as of the date the violation is cured, provided
367 | it is cured within 30 days of Your discovery of the
368 | violation; or
369 |
370 | 2. upon express reinstatement by the Licensor.
371 |
372 | For the avoidance of doubt, this Section 6(b) does not affect any
373 | right the Licensor may have to seek remedies for Your violations
374 | of this Public License.
375 |
376 | c. For the avoidance of doubt, the Licensor may also offer the
377 | Licensed Material under separate terms or conditions or stop
378 | distributing the Licensed Material at any time; however, doing so
379 | will not terminate this Public License.
380 |
381 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
382 | License.
383 |
384 |
385 | Section 7 -- Other Terms and Conditions.
386 |
387 | a. The Licensor shall not be bound by any additional or different
388 | terms or conditions communicated by You unless expressly agreed.
389 |
390 | b. Any arrangements, understandings, or agreements regarding the
391 | Licensed Material not stated herein are separate from and
392 | independent of the terms and conditions of this Public License.
393 |
394 |
395 | Section 8 -- Interpretation.
396 |
397 | a. For the avoidance of doubt, this Public License does not, and
398 | shall not be interpreted to, reduce, limit, restrict, or impose
399 | conditions on any use of the Licensed Material that could lawfully
400 | be made without permission under this Public License.
401 |
402 | b. To the extent possible, if any provision of this Public License is
403 | deemed unenforceable, it shall be automatically reformed to the
404 | minimum extent necessary to make it enforceable. If the provision
405 | cannot be reformed, it shall be severed from this Public License
406 | without affecting the enforceability of the remaining terms and
407 | conditions.
408 |
409 | c. No term or condition of this Public License will be waived and no
410 | failure to comply consented to unless expressly agreed to by the
411 | Licensor.
412 |
413 | d. Nothing in this Public License constitutes or may be interpreted
414 | as a limitation upon, or waiver of, any privileges and immunities
415 | that apply to the Licensor or You, including from the legal
416 | processes of any jurisdiction or authority.
417 |
418 | =======================================================================
419 |
420 | Creative Commons is not a party to its public
421 | licenses. Notwithstanding, Creative Commons may elect to apply one of
422 | its public licenses to material it publishes and in those instances
423 | will be considered the “Licensor.” The text of the Creative Commons
424 | public licenses is dedicated to the public domain under the CC0 Public
425 | Domain Dedication. Except for the limited purpose of indicating that
426 | material is shared under a Creative Commons public license or as
427 | otherwise permitted by the Creative Commons policies published at
428 | creativecommons.org/policies, Creative Commons does not authorize the
429 | use of the trademark "Creative Commons" or any other trademark or logo
430 | of Creative Commons without its prior written consent including,
431 | without limitation, in connection with any unauthorized modifications
432 | to any of its public licenses or any other arrangements,
433 | understandings, or agreements concerning use of licensed material. For
434 | the avoidance of doubt, this paragraph does not form part of the
435 | public licenses.
436 |
437 | Creative Commons may be contacted at creativecommons.org.
438 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 聪明办法学Python
2 |
3 | 大家好,我是小雨姑娘。双非本科自学数据挖掘,曾两次获得数据挖掘比赛冠军,被选入2020数据挖掘竞赛十大开源贡献者,人工智能开源组织Datawhale成员,现于北美攻读计算机博士学位。创作本教程的初心是提供一个更快捷有效的 Python 入门途径,让大家在最短时间内补充需要的知识技能,从而更快完成自己的目标。
4 |
5 | **学习完本教程你可以收获什么?**
6 |
7 | 1. 尝试使用Python完成项目解决问题的能力。
8 | 2. 对必备Python知识点的掌握。
9 | 3. 对经典理论与算法的了解。
10 |
11 | **本教程适合哪类同学学习?**
12 |
13 | 1. 想要从0开始系统学习 Python 的同学。
14 | 2. 需要在最短时间内学习 Python 解决当下问题的同学。
15 | 3. 对 Python 感兴趣想要了解的同学。
16 |
17 | **本教程不适合哪类同学学习?**
18 |
19 | 1. 希望精进 Python 高阶用法的同学。
20 | 2. 希望全面学习掌握 Python 知识点的同学。
21 |
22 | *在开发本教程的同时,作者也在构思一套有上述需求同学适合的教程。*
23 |
24 | **本教程相对市面其他材料的特点?**
25 |
26 | 1. 简明。专注 Python 编程的核心能力与技术,不涉及冷门/非必要相关知识。
27 | 2. 系统知识体系。从无到有一点点构建知识体系,拒绝琐碎知识点的堆叠。
28 | 3. 注重实践。通过代码讲解理论,辅以实例加以巩固。
29 |
30 | 柏拉图曾经说过:“良好的开端等于成功的一半”。大家选择本教程作为建起万丈高楼的地基,对于我而言便是莫大的荣幸。衷心希望大家在本教程陪伴下迈向未来的同时,也能享受学习过程中带来的乐趣。
31 |
32 | ## 如何使用这套教程?
33 | 1. 在 Github 网页版直接打开 ipynb 文件按顺序查看 (推荐)
34 | 2. 本地下载安装 jupyter notebook 运行 ipynb 文件,安装使用方法可参考这篇 [博客](https://www.jianshu.com/p/91365f343585/)
35 | 3. 在 [和鲸社区](https://www.heywhale.com) 创建项目,上传 .ipynb 文件可在线运行
36 | 4. 在 [Google Colab](https://www.colab.google.com) 上传 .ipynb 在线运行 (需要科学上网)
37 |
38 | ## 联系方式
39 | 知乎 [@小雨姑娘](https://www.zhihu.com/people/xuechuanyu)
40 |
41 | Email: chuanyu.xue@uconn.edu
42 |
43 | ## 关注我们
44 |
45 |
46 | ## LICENSE
47 | 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
48 |
--------------------------------------------------------------------------------
/src/fig11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig11.png
--------------------------------------------------------------------------------
/src/fig12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig12.png
--------------------------------------------------------------------------------
/src/fig13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig13.png
--------------------------------------------------------------------------------
/src/fig14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig14.png
--------------------------------------------------------------------------------
/src/fig41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig41.png
--------------------------------------------------------------------------------
/src/fig42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig42.png
--------------------------------------------------------------------------------
/src/fig43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig43.png
--------------------------------------------------------------------------------
/src/fig44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/datawhalechina/learn-python-the-smart-way/1fffb6f468888a11e1485c58051f274b4b772ff0/src/fig44.png
--------------------------------------------------------------------------------
| | | |