├── 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 |
Datawhale是一个专注AI领域的开源组织,以“for the learner,和学习者一起成长”为愿景,构建对学习者最有价值的开源学习社区。关注我们,一起学习成长。
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 --------------------------------------------------------------------------------