├── README.md
├── day01
└── index.md
├── day02
├── code
│ ├── practice1.py
│ ├── practice2.py
│ └── practice3.py
└── index.md
├── day03
├── code
│ ├── practice1.py
│ ├── practice2.py
│ ├── practice2_1.py
│ ├── practice3.py
│ ├── practice4.py
│ └── practice5.py
└── index.md
├── day04
├── code
│ ├── practice1.py
│ ├── practice2.py
│ └── practice3.py
└── index.md
├── day05
├── code
│ ├── practice1.py
│ ├── practice2.py
│ ├── practice3.py
│ ├── practice4.py
│ └── practice5.py
└── index.md
├── day06
├── code
│ ├── practice1.py
│ ├── practice2.py
│ ├── practice2_1.py
│ └── practice3.py
└── index.md
├── day07
├── code
│ ├── case1.py
│ ├── case2.py
│ ├── case3.py
│ ├── practice1.py
│ ├── practice2.py
│ ├── practice3.py
│ ├── practice4.py
│ ├── practice5.py
│ └── practice6.py
└── index.md
├── day08
├── code
│ ├── practice1.py
│ └── practice2.py
└── index.md
├── day09
├── code
│ ├── case1.py
│ ├── case2.py
│ └── case3.py
└── index.md
├── day11
└── index.md
├── day12
└── index.md
├── day13
└── index.md
├── day14-a
└── index.md
├── day14-b
└── index.md
├── img
├── day01
│ └── task-2.png
├── day11
│ └── file-open-mode.png
└── icon.png
├── res
├── 01.django_single_server.png
├── 02.django_dedicated_db_server.png
├── 03.django_dedicated_static_server.png
├── 04.django_load_balance.png
├── 05.django_massive_cluster.png
├── Celery_RabitMQ.png
├── Producer-Broker-Consumer-Arrangement.png
├── abstraction-view.png
├── algorithm_complexity_1.png
├── algorithm_complexity_2.png
├── alipay_web_developer.png
├── aliyun-certificate.png
├── aliyun-dnslist.png
├── aliyun-domain.png
├── aliyun-keeprecord.png
├── aliyun-resolve-settings.png
├── app_folder_arch.png
├── builtin-middlewares.png
├── celery.png
├── celery_architecture.png
├── class-and-object.png
├── click-jacking.png
├── company_architecture.png
├── concurrency.png
├── deployment_pipelines.png
├── django-middleware.png
├── django-mtv.png
├── django_request_response_cycle.png
├── docker_logo.png
├── docker_vs_vm.png
├── encapsulation.png
├── er-graph.png
├── git_logo.png
├── git_repository.png
├── gitignore_io.png
├── greedy.png
├── hadoop_ecosystem.png
├── http-request.png
├── http-response.png
├── int-is-comparation.png
├── jenkins_new_project.png
├── modularity.png
├── multi-inheritance.png
├── mvc.png
├── oauth2.png
├── object-roles.png
├── objects-collaborate.png
├── objects-lifetime.png
├── power-designer-pdm.png
├── pycharm-activate.png
├── pycharm-comm-django-1.png
├── pycharm-comm-django-2.png
├── pycharm-comm-django-3.png
├── pycharm-comm-django-4.png
├── pycharm-comm-django-5.png
├── pycharm-comm-django-6.png
├── pycharm-comm-django-7.png
├── pycharm-comm-django-8.png
├── pycharm-create-launcher-script.png
├── pycharm-import-settings.png
├── pycharm-new-project.png
├── pycharm-plugins.png
├── pycharm-prof-django-2.png
├── pycharm-prof-django-3.png
├── pycharm-set-ui-theme.png
├── pycharm-welcome.png
├── pycharm-workspace.png
├── pylint.png
├── python-bj-salary.png
├── python-built-in-functions.png
├── python-cd-salary.png
├── python-job-all.png
├── python-job-chengdu.png
├── python-salary-beijing.png
├── python-salary-chengdu.png
├── python-salary-hangzhou.png
├── python-salary-shanghai.png
├── python-salary-shenzhen.png
├── python-salary.png
├── python-str-join.png
├── python-top-10.png
├── python-tutor-visualize.png
├── python-tutor-visualize2.png
├── python_jobs_chengdu.png
├── python_salary_chengdu.png
├── python_salary_guangzhou.png
├── rbac-basic.png
├── rbac-full.png
├── redmine_new_issue.png
├── requirements_by_xmind.png
├── result-of-dis.png
├── selenium-ide.png
├── selenium_ide.png
├── shopping-pdm.png
├── the-daily-scrum-in-the-sprint-cycle.png
├── uml-class-diagram.png
├── uml-graph.png
├── uml.png
├── web-application.png
├── web-queue-worker-physical.png
└── zen-of-python.png
└── rule.md
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 | # Python 100 Pratice
4 |
5 | Python 100 天从新手到大师个人学习笔记与实践。
6 |
7 | 课程来自于 [骆昊](https://github.com/jackfrued) 老师的 [Python - 100天从新手到大师](https://github.com/jackfrued/Python-100-Days)。
8 |
9 | 现从 2019.05.19 开始为期 100 天的课程学习之旅,将在本仓库记录学习笔记与练习题。
10 |
11 | ## 课程列表
12 |
13 | ### Day01~15 - [Python语言基础](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15)
14 |
15 | #### ✅ Day01 - [初识Python](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day01/初识Python.md)
16 |
17 | 学习笔记:[Day01 学习笔记](/day01/index.md)
18 |
19 | - [x] Python简介 - Python的历史 / Python的优缺点 / Python的应用领域
20 | - [x] 搭建编程环境 - Windows环境 / Linux环境 / MacOS环境
21 | - [x] 从终端运行Python程序 - DOS命令 / Hello, world / print函数 / 运行程序
22 | - [x] 使用IDLE - 交互式环境(REPL) / 编写多行代码 / 运行程序 / 退出IDLE
23 | - [x] 注释 - 注释的作用 / 单行注释 / 多行注释
24 |
25 | #### ✅ Day02 - [语言元素](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day02/语言元素.md)
26 |
27 | 学习笔记:[Day02 学习笔记](/day02/index.md)
28 |
29 | - [x] 程序和进制 - 指令和程序 / 冯诺依曼机 / 二进制和十进制 / 八进制和十六进制
30 | - [x] 变量和类型 - 变量的命名 / 变量的使用 / input函数 / 检查变量类型 / 类型转换
31 | - [x] 数字和字符串 - 整数 / 浮点数 / 复数 / 字符串 / 字符串基本操作 / 字符编码
32 | - [x] 运算符 - 数学运算符 / 赋值运算符 / 比较运算符 / 逻辑运算符 / 身份运算符 / 运算符的优先级
33 | - [x] 应用案例 - 华氏温度转换成摄氏温度 / 输入圆的半径计算周长和面积 / 输入年份判断是否是闰年
34 | - [ ] 复习冯诺依曼机
35 |
36 | #### ✅ Day03 - [分支结构](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day03/分支结构.md)
37 |
38 | 学习笔记:[Day03 学习笔记](/day03/index.md)
39 |
40 | - [x] 分支结构的应用场景 - 条件 / 缩进 / 代码块 / 流程图
41 | - [x] if语句 - 简单的if / if-else结构 / if-elif-else结构 / 嵌套的if
42 | - [x] 应用案例 - 用户身份验证 / 英制单位与公制单位互换 / 掷骰子决定做什么 / 百分制成绩转等级制 / 分段函数求值 / 输入三条边的长度如果能构成三角形就计算周长和面积
43 |
44 | #### ✅ Day04 - [循环结构](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day04/循环结构.md)
45 |
46 | 学习笔记:[Day04 学习笔记](/day04/i
47 |
48 | - [x] 循环结构的应用场景 - 条件 / 缩进 / 代码块 / 流程图
49 | - [x] while循环 - 基本结构 / break语句 / continue语句
50 | - [x] for循环 - 基本结构 / range类型 / 循环中的分支结构 / 嵌套的循环 / 提前结束程序
51 | - [x] 应用案例 - 1~100求和 / 判断素数 / 猜数字游戏 / 打印九九表 / 打印三角形图案 / 猴子吃桃 / 百钱百鸡(???好像没有看到 猴子吃桃 / 百钱百鸡)
52 |
53 | #### ✅ Day05 - [总结和练习](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day05/总结和练习.md)
54 |
55 | 学习笔记:[Day05 学习笔记](/day05/index.md)
56 |
57 | - [x] 基础练习 - 水仙花数 / 完美数 / 五人分鱼 / Fibonacci数列 / 回文素数
58 | - [x] 综合练习 - Craps赌博游戏
59 |
60 | #### ✅ Day06 - [函数和模块的使用](https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day06/函数和模块的使用.md)
61 |
62 | 学习笔记:[Day06 学习笔记](/day06/index.md)
63 |
64 | - [x] 函数的作用 - 代码的坏味道 / 用函数封装功能模块
65 | - [x] 定义函数 - def语句 / 函数名 / 参数列表 / return语句 / 调用自定义函数
66 | - [x] 调用函数 - Python内置函数 / 导入模块和函数
67 | - [x] 函数的参数 - 默认参数 / 可变参数 / 关键字参数 / 命名关键字参数
68 | - [x] 函数的返回值 - 没有返回值 / 返回单个值 / 返回多个值
69 | - [x] 作用域问题 - 局部作用域 / 嵌套作用域 / 全局作用域 / 内置作用域 / 和作用域相关的关键字
70 | - [x] 用模块管理函数 - 模块的概念 / 用自定义模块管理函数 / 命名冲突的时候会怎样(同一个模块和不同的模块)
71 |
72 | #### ✅ Day07 - [字符串和常用数据结构](./Day01-15/Day07/字符串和常用数据结构.md)
73 |
74 | 学习笔记:[Day07 学习笔记](/day07/index.md)
75 |
76 | - [x] 字符串的使用 - 计算长度 / 下标运算 / 切片 / 常用方法
77 | - [x] 列表基本用法 - 定义列表 / 用下表访问元素 / 下标越界 / 添加元素 / 删除元素 / 修改元素 / 切片 / 循环遍历
78 | - [x] 列表常用操作 - 连接 / 复制(复制元素和复制数组) / 长度 / 排序 / 倒转 / 查找
79 | - [x] 生成列表 - 使用range创建数字列表 / 生成表达式 / 生成器
80 | - [x] 元组的使用 - 定义元组 / 使用元组中的值 / 修改元组变量 / 元组和列表转换
81 | - [x] 集合基本用法 - 集合和列表的区别 / 创建集合 / 添加元素 / 删除元素 / 清空
82 | - [x] 集合常用操作 - 交集 / 并集 / 差集 / 对称差 / 子集 / 超集
83 | - [x] 字典的基本用法 - 字典的特点 / 创建字典 / 添加元素 / 删除元素 / 取值 / 清空
84 | - [x] 字典常用操作 - keys()方法 / values()方法 / items()方法 / setdefault()方法
85 | - [x] 基础练习 - 跑马灯效果 / 列表找最大元素 / 统计考试成绩的平均分 / Fibonacci数列 / 杨辉三角
86 | - [x] 综合案例 - 双色球选号 / 井字棋
87 |
88 | #### ✅ Day08 - [面向对象编程基础](./Day01-15/Day08/面向对象编程基础.md)
89 |
90 | 学习笔记:[Day08 学习笔记](/day08/index.md)
91 |
92 | - [x] 类和对象 - 什么是类 / 什么是对象 / 面向对象其他相关概念
93 | - [x] 定义类 - 基本结构 / 属性和方法 / 构造器 / 析构器 / \_\_str\_\_方法
94 | - [x] 使用对象 - 创建对象 / 给对象发消息
95 | - [x] 面向对象的四大支柱 - 抽象 / 封装 / 继承 / 多态
96 | - [x] 基础练习 - 定义学生类 / 定义时钟类 / 定义图形类 / 定义汽车类
97 |
98 | #### ✅ Day09 - [面向对象进阶](./Day01-15/Day09/面向对象进阶.md)
99 |
100 | 学习笔记:[Day09 学习笔记](/day09/index.md)
101 |
102 | - [x] 属性 - 类属性 / 实例属性 / 属性访问器 / 属性修改器 / 属性删除器 / 使用\_\_slots\_\_
103 | - [x] 类中的方法 - 实例方法 / 类方法 / 静态方法
104 | - [x] 运算符重载 - \_\_add\_\_ / \_\_sub\_\_ / \_\_or\_\_ /\_\_getitem\_\_ / \_\_setitem\_\_ / \_\_len\_\_ / \_\_repr\_\_ / \_\_gt\_\_ / \_\_lt\_\_ / \_\_le\_\_ / \_\_ge\_\_ / \_\_eq\_\_ / \_\_ne\_\_ / \_\_contains\_\_
105 | - [x] 类(的对象)之间的关系 - 关联 / 继承 / 依赖
106 | - [x] 继承和多态 - 什么是继承 / 继承的语法 / 调用父类方法 / 方法重写 / 类型判定 / 多重继承 / 菱形继承(钻石继承)和C3算法
107 | - [ ] 综合案例
108 | - 工资结算系统
109 | - 图书自动折扣系统
110 | - 自定义分数类
111 |
112 | #### Day10 - [图形用户界面和游戏开发](./Day01-15/Day10/图形用户界面和游戏开发.md)
113 |
114 | - 使用tkinter开发GUI
115 | - 使用pygame三方库开发游戏应用
116 | - “大球吃小球”游戏
117 |
118 | #### ✅ Day11 - [文件和异常](./Day01-15/Day11/文件和异常.md)
119 |
120 | 学习笔记:[Day11 学习笔记](/day11/index.md)
121 |
122 | - [x] 读文件 - 读取整个文件 / 逐行读取 / 文件路径
123 | - [x] 写文件 - 覆盖写入 / 追加写入 / 文本文件 / 二进制文件
124 | - [x] 异常处理 - 异常机制的重要性 / try-except代码块 / else代码块 / finally代码块 / 内置异常类型 / 异常栈 / raise语句
125 | - [x] 数据持久化 - CSV文件概述 / csv模块的应用 / JSON数据格式 / json模块的应用
126 | - [ ] 综合案例 - 歌词解析
127 |
128 | #### ✅ Day12 - [字符串和正则表达式](./Day01-15/Day12/字符串和正则表达式.md)
129 |
130 | 学习笔记:[Day12 学习笔记](/day12/index.md)
131 |
132 | - [ ] 字符串高级操作 - 转义字符 \ 原始字符串 \ 多行字符串 \ in和 not in运算符 \ is开头的方法 \ join和split方法 \ strip相关方法 \ pyperclip模块 \ 不变字符串和可变字符串 \ StringIO的使用
133 | - [x] 正则表达式入门 - 正则表达式的作用 \ 元字符 \ 转义 \ 量词 \ 分组 \ 零宽断言 \贪婪匹配与惰性匹配懒惰 \ 使用re模块实现正则表达式操作(匹配、搜索、替换、捕获)
134 | - [x] 使用正则表达式 - re模块 \ compile函数 \ group和groups方法 \ match方法 \ search方法 \ findall和finditer方法 \ sub和subn方法 \ split方法
135 | - [ ] 应用案例 - 使用正则表达式验证输入的字符串
136 |
137 | #### ✅ Day13 - [进程和线程](./Day01-15/Day13/进程和线程.md)
138 |
139 | 学习笔记:[Day13 学习笔记](/day13/index.md)
140 |
141 | - [x] 进程和线程的概念 - 什么是进程 / 什么是线程 / 多线程的应用场景
142 | - [x] 使用进程 - fork函数 / multiprocessing模块 / 进程池 / 进程间通信
143 | - [x] 使用线程 - thread模块 / threading模块 / Thread类 / Lock类 / Condition类 / 线程池
144 |
145 | #### ✅ Day14-A - [网络编程入门](./Day01-15/Day14-A/网络编程入门.md)
146 |
147 | 学习笔记:[Day14-A 学习笔记](/day14-a/index.md)
148 |
149 | - [x] 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念
150 | - [x] 网络应用架构 - “客户端-服务器”架构 / “浏览器-服务器”架构
151 | - [x] Python网络编程 - 套接字的概念 / socket模块 / socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 / SocketServer模块
152 |
153 | #### Day14-B - [网络应用开发](./Day01-15/Day14-B/网络应用开发.md)
154 |
155 | - 访问网络API
156 | - 网络API概述
157 | - 访问URL
158 | - requests模块
159 | - 解析JSON格式数据
160 | - 文件传输
161 | - FTP协议
162 | - ftplib模块
163 | - 交互式FTP应用
164 | - 电子邮件
165 | - [x] SMTP协议
166 | - POP3协议
167 | - IMAP协议
168 | - [x] smtplib模块
169 | - poplib模块
170 | - imaplib模块
171 | - 短信服务
172 | - twilio模块
173 | - [x] 国内的短信服务
174 |
175 | #### Day15 - [图像和文档处理](./Day01-15/Day15/图像和办公文档处理.md)
176 |
177 | - 用Pillow处理图片 - 图片读写 / 图片合成 / 几何变换 / 色彩转换 / 滤镜效果
178 | - 读写Word文档 - 文本内容的处理 / 段落 / 页眉和页脚 / 样式的处理
179 | - 读写Excel文件 - xlrd模块 / xlwt模块
180 | - 生成PDF文件 - pypdf2模块 / reportlab模块
181 |
182 | ### Day16~Day20 - [Python语言进阶 ](./Day16-20/Python语言进阶.md)
183 |
184 | - 常用数据结构
185 | - 函数的高级用法 - “一等公民” / 高阶函数 / Lambda函数 / 作用域和闭包 / 装饰器
186 | - 面向对象高级知识 - “三大支柱” / 类与类之间的关系 / 垃圾回收 / 魔术属性和方法 / 混入 / 元类 / 面向对象设计原则 / GoF设计模式
187 | - 迭代器和生成器 - 相关魔术方法 / 创建生成器的两种方式 /
188 | - 并发和异步编程 - 多线程 / 多进程 / 异步IO / async和await
189 |
190 | ### Day21~30 - [Web前端入门](./Day21-30/Web前端概述.md)
191 |
192 | - 用HTML标签承载页面内容
193 | - 用CSS渲染页面
194 | - 用JavaScript处理交互式行为
195 | - jQuery入门和提高
196 | - Vue.js入门
197 | - Element的使用
198 | - Bootstrap的使用
199 |
200 | ### Day31~35 - [玩转Linux操作系统](./Day31-35/玩转Linux操作系统.md)
201 |
202 | - 操作系统发展史和Linux概述
203 | - Linux基础命令
204 | - Linux中的实用程序
205 | - Linux的文件系统
206 | - Vim编辑器的应用
207 | - 环境变量和Shell编程
208 | - 软件的安装和服务的配置
209 | - 网络访问和管理
210 | - 其他相关内容
211 |
212 | ### Day36~40 - [数据库基础和进阶](./Day36-40)
213 |
214 | - [关系型数据库MySQL](./Day36-40/关系型数据库MySQL.md)
215 | - 关系型数据库概述
216 | - MySQL的安装和使用
217 | - SQL的使用
218 | - DDL - 数据定义语言 - create / drop / alter
219 | - DML - 数据操作语言 - insert / delete / update / select
220 | - DCL - 数据控制语言 - grant / revoke
221 | - 相关知识
222 | - 范式理论 - 设计二维表的指导思想
223 | - 数据完整性
224 | - 数据一致性
225 | - 在Python中操作MySQL
226 | - [NoSQL入门](./Day36-40/NoSQL入门.md)
227 | - NoSQL概述
228 | - Redis概述
229 | - Mongo概述
230 |
231 | ### Day41~55 - [实战Django](./Day41-55)
232 |
233 | #### Day41 - [快速上手](./Day41-55/01.快速上手.md)
234 |
235 | - Web应用工作原理和HTTP协议
236 | - Django框架概述
237 | - 5分钟快速上手
238 | - 使用视图模板
239 |
240 | #### Day42 - [深入模型](./Day41-55/02.深入模型.md)
241 |
242 | - 关系型数据库配置
243 | - 管理后台的使用
244 | - 使用ORM完成对模型的CRUD操作
245 | - Django模型最佳实践
246 | - 模型定义参考
247 |
248 | #### Day43 - [静态资源和Ajax请求](./Day41-55/03.静态资源和Ajax请求.md)
249 |
250 | - 加载静态资源
251 | - 用Ajax请求获取数据
252 |
253 | #### Day44 - [表单的应用](./Day41-55/04.表单的应用.md)
254 |
255 | #### Day45 - [Cookie和Session](./Day41-55/05.Cookie和Session.md)
256 |
257 | #### Day46 - [中间件的应用](./Day41-55/06.中间件的应用.md)
258 |
259 | #### Day47 - [日志和缓存](./Day41-55/07.日志和缓存.md)
260 |
261 | #### Day48 - [文件上传和富文本编辑](./Day41-55/08.文件上传.md)
262 |
263 | #### Day49 - [文件下载和报表](./Day41-55/09.文件下载和报表.md)
264 |
265 | #### Day50 - [RESTful架构和DRF入门](./Day41-55/10.RESTful架构和DRF入门.md)
266 |
267 | #### Day51 - [RESTful架构和DRF进阶](./Day41-55/11.RESTful架构和DRF进阶.md)
268 |
269 | #### Day52 - [使用缓存](./Day41-55/12.使用缓存.md)
270 |
271 | #### Day53 - [短信和邮件](./Day41-55/13.短信和邮件.md)
272 |
273 | #### Day54 - [异步任务和定时任务](./Day41-55/14.异步任务和定时任务.md)
274 |
275 | #### Day55 - [单元测试和项目上线](./Day41-55/15.单元测试和项目上线.md)
276 |
277 | - 项目开发流程和相关工具
278 | - 生成非HTML内容
279 | - 项目部署和测试
280 | - 项目性能初步调优
281 | - Web应用安全保护
282 |
283 |
284 | ### Day56~60 - [实战Flask](./Day56-65)
285 |
286 | #### Day56 - [Flask入门](./Day56-60/01.Flask入门.md)
287 |
288 | #### Day57 - [模板的使用](./Day56-60/02.模板的使用.md)
289 |
290 | #### Day58 - [表单的处理](./Day56-60/03.表单的处理.md)
291 |
292 | #### Day59 - [数据库操作](./Day56-60/04.数据库操作.md)
293 |
294 | #### Day60 - [项目实战](./Day56-60/05.项目实战.md)
295 |
296 | ### Day61~65 - [实战Tornado](./Day61-65)
297 |
298 | #### Day61 - [预备知识](./Day61-65/01.预备知识.md)
299 |
300 | - 并发编程
301 | - I/O模式和事件驱动
302 |
303 | #### Day62 - [Tornado入门](./Day61-65/02.Tornado入门.md)
304 |
305 | - Tornado概述
306 | - 5分钟上手Tornado
307 | - 路由解析
308 | - 请求处理器
309 |
310 | #### Day63 - [异步化](./Day61-65/03.异步化.md)
311 |
312 | - aiomysql和aioredis的使用
313 |
314 | #### Day64 - [WebSocket的应用](./Day61-65/04.WebSocket的应用.md)
315 |
316 | - WebSocket简介
317 | - WebSocket服务器端编程
318 | - WebSocket客户端编程
319 | - 项目:Web聊天室
320 |
321 | #### Day65 - [项目实战](./Day61-65/05.项目实战.md)
322 |
323 | - 前后端分离开发和接口文档的撰写
324 | - 使用Vue.js实现前端渲染
325 | - 使用ECharts实现报表功能
326 | - 使用WebSocket实现推送服务
327 |
328 | ### Day66~75 - [爬虫开发](./Day66-75)
329 |
330 | #### Day66 - [网络爬虫和相关工具](./Day66-75/01.网络爬虫和相关工具.md)
331 |
332 | #### Day67 - [数据采集和解析](./Day66-75/02.数据采集和解析.md)
333 |
334 | #### Day68 - [存储数据](./Day66-75/03.存储数据.md)
335 |
336 | #### Day69 - [并发下载](./Day66-75/04.并发下载.md)
337 |
338 | #### Day70 - [解析动态内容](./Day66-75/05.解析动态内容.md)
339 |
340 | #### Day71 - [表单交互和验证码处理](./Day66-75/06.表单交互和验证码处理.md)
341 |
342 | #### Day72 - [Scrapy入门](./Day66-75/07.Scrapy入门.md)
343 |
344 | #### Day73 - [Scrapy高级应用](./Day66-75/08.Scrapy高级应用.md)
345 |
346 | #### Day74 - [Scrapy分布式实现](./Day66-75/09.Scrapy分布式实现.md)
347 |
348 | #### Day75 - [爬虫项目实战](./Day66-75/10.爬虫项目实战.md)
349 |
350 | ### Day76~90 - [数据处理和机器学习](./Day76-90)
351 |
352 | #### Day76 - [机器学习基础](./Day76-90/01.机器学习基础.md)
353 |
354 | #### Day77 - [Pandas的应用](./Day76-90/02.Pandas的应用.md)
355 |
356 | #### Day78 - [NumPy和SciPy的应用](./Day76-90/03.NumPy和SciPy的应用)
357 |
358 | #### Day79 - [Matplotlib和数据可视化](./Day76-90/04.Matplotlib和数据可视化)
359 |
360 | #### Day80 - [k最近邻(KNN)分类](./Day76-90/05.k最近邻分类.md)
361 |
362 | #### Day81 - [决策树](./Day76-90/06.决策树.md)
363 |
364 | #### Day82 - [贝叶斯分类](./Day76-90/07.贝叶斯分类.md)
365 |
366 | #### Day83 - [支持向量机(SVM)](./Day76-90/08.支持向量机.md)
367 |
368 | #### Day84 - [K-均值聚类](./Day76-90/09.K-均值聚类.md)
369 |
370 | #### Day85 - [回归分析](./Day76-90/10.回归分析.md)
371 |
372 | #### Day86 - [大数据分析入门](./Day76-90/11.大数据分析入门.md)
373 |
374 | #### Day87 - [大数据分析进阶](./Day76-90/12.大数据分析进阶.md)
375 |
376 | #### Day88 - [Tensorflow入门](./Day76-90/13.Tensorflow入门.md)
377 |
378 | #### Day89 - [Tensorflow实战](./Day76-90/14.Tensorflow实战.md)
379 |
380 | #### Day90 - [推荐系统](./Day76-90/15.推荐系统.md)
381 |
382 | ### Day91~100 - [团队项目开发](./Day91-100)
383 |
384 | #### 第91天:团队开发和项目选题
385 |
386 | 1. 软件过程模型
387 | - 经典过程模型(瀑布模型)
388 | - 可行性分析(研究做还是不做),输出《可行性分析报告》。
389 | - 需求分析(研究做什么),输出《需求规格说明书》和产品界面原型图。
390 | - 概要设计和详细设计,输出概念模型图、物理模型图、类图、时序图等。
391 | - 编码 / 测试。
392 | - 上线 / 维护。
393 | - 敏捷开发(Scrum)- 产品所有者、Scrum Master、研发人员 - Sprint
394 | - 产品的Backlog(用户故事、产品原型)。
395 | - 计划会议(评估和预算)。
396 | - 日常开发(站立会议、番茄工作法、结对编程、测试先行、代码重构……)。
397 | - 修复bug(问题描述、重现步骤、测试人员、被指派人)。
398 | - 评审会议(Showcase)。
399 | - 回顾会议(当前周期做得好和不好的地方)。
400 |
401 | > 补充:敏捷软件开发宣言
402 | >
403 | > - **个体和互动** 高于 流程和工具
404 | > - **工作的软件** 高于 详尽的文档
405 | > - **客户合作** 高于 合同谈判
406 | > - **响应变化** 高于 遵循计划
407 |
408 | 
409 |
410 | > 角色:产品所有者(决定做什么,能对需求拍板的人)、团队负责人(解决各种问题,专注如何更好的工作,屏蔽外部对开发团队的影响)、开发团队(项目执行人员,具体指开发人员和测试人员)。
411 | >
412 | > 准备工作:商业案例和资金、合同、憧憬、初始产品需求、初始发布计划、入股、组建团队。
413 | >
414 | > 敏捷团队通常人数为8-10人。
415 | >
416 | > 工作量估算:将开发任务量化,包括原型、Logo设计、UI设计、前端开发等,尽量把每个工作分解到最小任务量,最小任务量标准为工作时间不能超过两天,然后估算总体项目时间。把每个任务都贴在白板上面,白板上分三部分:to do(待完成)、in progress(进行中)和done(已完成)。
417 |
418 | 2. 项目团队组建
419 |
420 | - 团队的构成和角色
421 |
422 | > 说明:谢谢付祥英女士绘制了下面这张精美的公司组织架构图。
423 |
424 | 
425 |
426 | - 编程规范和代码审查(flake8、pylint)
427 |
428 | 
429 |
430 | - Python中的一些“惯例”(请参考[《Python惯例-如何编写Pythonic的代码》](Python惯例.md))
431 |
432 | - 影响代码可读性的原因:
433 |
434 | - 代码注释太少或者没有注释
435 | - 代码破坏了语言的最佳实践
436 | - 反模式编程(意大利面代码、复制-黏贴编程、自负编程、……)
437 |
438 | 3. 团队开发工具介绍
439 | - 版本控制:Git、Mercury
440 | - 缺陷管理:[Gitlab](https://about.gitlab.com/)、[Redmine](http://www.redmine.org.cn/)
441 | - 敏捷闭环工具:[禅道](https://www.zentao.net/)、[JIRA](https://www.atlassian.com/software/jira/features)
442 | - 持续集成:[Jenkins](https://jenkins.io/)、[Travis-CI](https://travis-ci.org/)
443 |
444 | 请参考[《团队项目开发》](Day91-100/团队项目开发.md)。
445 |
446 | ##### 项目选题和理解业务
447 |
448 | 1. 选题范围设定
449 |
450 | - CMS(用户端):新闻聚合网站、问答/分享社区、影评/书评网站等。
451 | - MIS(用户端+管理端):KMS、KPI考核系统、HRS、CRM系统、供应链系统、仓储管理系统等。
452 |
453 | - App后台(管理端+数据接口):二手交易类、报刊杂志类、小众电商类、新闻资讯类、旅游类、社交类、阅读类等。
454 | - 其他类型:自身行业背景和工作经验、业务容易理解和把控。
455 |
456 | 2. 需求理解、模块划分和任务分配
457 |
458 | - 需求理解:头脑风暴和竞品分析。
459 | - 模块划分:画思维导图(XMind),每个模块是一个枝节点,每个具体的功能是一个叶节点(用动词表述),需要确保每个叶节点无法再生出新节点,确定每个叶子节点的重要性、优先级和工作量。
460 | - 任务分配:由项目负责人根据上面的指标为每个团队成员分配任务。
461 |
462 | 
463 |
464 | 3. 制定项目进度表(每日更新)
465 |
466 | | 模块 | 功能 | 人员 | 状态 | 完成 | 工时 | 计划开始 | 实际开始 | 计划结束 | 实际结束 | 备注 |
467 | | ---- | -------- | ------ | -------- | ---- | ---- | -------- | -------- | -------- | -------- | ---------------- |
468 | | 评论 | 添加评论 | 王大锤 | 正在进行 | 50% | 4 | 2018/8/7 | | 2018/8/7 | | |
469 | | | 删除评论 | 王大锤 | 等待 | 0% | 2 | 2018/8/7 | | 2018/8/7 | | |
470 | | | 查看评论 | 白元芳 | 正在进行 | 20% | 4 | 2018/8/7 | | 2018/8/7 | | 需要进行代码审查 |
471 | | | 评论投票 | 白元芳 | 等待 | 0% | 4 | 2018/8/8 | | 2018/8/8 | | |
472 |
473 | #### 第92天:数据库设计和OOAD
474 |
475 | ##### 概念模型和正向工程
476 |
477 | 1. UML(统一建模语言)的类图
478 |
479 | 
480 |
481 | 2. 通过模型创建表(正向工程)
482 |
483 | ```Shell
484 | python manage.py makemigrations app
485 | python manage.py migrate
486 | ```
487 |
488 | ##### 物理模型和反向工程
489 |
490 | 1. PowerDesigner
491 |
492 | 
493 |
494 | 2. 通过数据表创建模型(反向工程)
495 |
496 | ```Shell
497 | python manage.py inspectdb > app/models.py
498 | ```
499 |
500 | #### 第93-98天:使用Django开发项目
501 |
502 | > 说明:具体内容请参考[《Django知识点概述》](Day91-100/Django知识点概述.md)
503 |
504 | ##### 项目开发中的公共问题
505 |
506 | 1. 数据库的配置(多数据库、主从复制、数据库路由)
507 | 2. 缓存的配置(分区缓存、键设置、超时设置、主从复制、故障恢复(哨兵))
508 | 3. 日志的配置
509 | 4. 分析和调试(Django-Debug-ToolBar)
510 | 5. 好用的Python模块(日期计算、图像处理、数据加密、三方API)
511 |
512 | ##### REST API设计
513 |
514 | 1. RESTful架构
515 | - [理解RESTful架构](http://www.ruanyifeng.com/blog/2011/09/restful.html)
516 | - [RESTful API设计指南](http://www.ruanyifeng.com/blog/2014/05/restful_api.html)
517 | - [RESTful API最佳实践](http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html)
518 | 2. API接口文档的撰写([《网络API接口设计》](Day91-100/网络API接口设计.md))
519 | - [RAP2](http://rap2.taobao.org/)
520 | - [YAPI](http://yapi.demo.qunar.com/)
521 | 3. [django-REST-framework](https://www.django-rest-framework.org/)的应用
522 |
523 | ##### 项目中的重点难点剖析
524 |
525 | 1. 使用缓存缓解数据库压力 - Redis
526 | 2. 使用消息队列做解耦合和削峰 - Celery + RabbitMQ
527 |
528 | #### 第99-100天:测试和部署
529 |
530 | ##### 单元测试
531 |
532 | 1. 测试的种类
533 | 2. 编写单元测试(unittest、pytest、nose2、tox、ddt、……)
534 | 3. 测试覆盖率(coverage)
535 |
536 | ##### 项目部署
537 |
538 | > 说明:请参考[《项目部署上线指南》](Day91-100/项目部署上线指南.md)。
539 |
540 | 1. 部署前的准备工作
541 | - 关键设置(SECRET_KEY / DEBUG / ALLOWED_HOSTS / 缓存 / 数据库)
542 | - HTTPS / CSRF_COOKIE_SECUR / SESSION_COOKIE_SECURE
543 | - 日志相关配置
544 | 2. Linux常用命令回顾
545 | 3. Linux常用服务的安装和配置
546 | 4. uWSGI/Gunicorn和Nginx的使用
547 | - Gunicorn和uWSGI的比较
548 | - 对于不需要大量定制化的简单应用程序,Gunicorn是一个不错的选择,uWSGI的学习曲线比Gunicorn要陡峭得多,Gunicorn的默认参数就已经能够适应大多数应用程序。
549 | - uWSGI支持异构部署。
550 | - 由于Nginx本身支持uWSGI,在线上一般都将Nginx和uWSGI捆绑在一起部署,而且uWSGI属于功能齐全且高度定制的WSGI中间件。
551 | - 在性能上,Gunicorn和uWSGI其实表现相当。
552 | 5. 虚拟化技术(Docker)
553 |
554 | ##### 性能测试
555 |
556 | > 说明:具体内容请参考[《Django知识点概述》](Day91-100/Django知识点概述.md)。
557 |
558 | 1. AB的使用
559 | 2. SQLslap的使用
560 | 3. sysbench的使用
561 |
562 | ##### 自动化测试
563 |
564 | 1. 使用Shell和Python进行自动化测试
565 | 2. 使用Selenium实现自动化测试
566 | - Selenium IDE
567 | - Selenium WebDriver
568 | - Selenium Remote Control
569 | 3. 测试工具Robot Framework介绍
570 |
571 | ##### 项目性能调优
572 |
573 | 1. 数据库性能调优 - 请参考[《MySQL相关知识》](Day91-100/MySQL相关知识.md)
574 | - 软硬件优化
575 |
576 | - SQL优化
577 |
578 | - 架构优化
579 |
580 | - 分表分库
581 |
582 | - 主从复制,读写分离
583 | - 集群架构
584 |
585 | 2. Web服务器性能优化
586 |
587 | - Nginx负载均衡配置
588 |
589 | - Keepalived实现高可用
590 |
591 | 3. 代码性能调优
592 |
593 | - 多线程
594 | - 异步化
595 |
596 | 4. 静态资源访问优化
597 | - 云存储
598 | - CDN
--------------------------------------------------------------------------------
/day01/index.md:
--------------------------------------------------------------------------------
1 | # Day01 - 初识Python
2 |
3 | ## Python 简介
4 |
5 | - Python 3.x 的很多新特性后来也被移植到 Python 2.6/2.7 版本中
6 | - 多行注释 - 三个引号开头,三个引号结尾
7 | - [Anaconda](https://baike.baidu.com/item/anaconda/20407441?fr=aladdin) 是一个开源的 Python 发行版本,其包含了 conda、Python 等 180 多个科学包及其依赖项
8 |
9 | ## Python 环境
10 |
11 | ### 安装交互式工具
12 |
13 | ```
14 | $ pip3 install ipython jupyter
15 | ```
16 |
17 | ----
18 |
19 | ## 作业
20 |
21 | ### 1. Python 之禅
22 |
23 | 启动 IPython:
24 |
25 | ```
26 | $ ipython
27 | ```
28 |
29 | 启动后输入 `import this` 会看到以下输出:
30 |
31 | ```python
32 | In [1]: import this
33 | The Zen of Python, by Tim Peters
34 |
35 | Beautiful is better than ugly.
36 | Explicit is better than implicit.
37 | Simple is better than complex.
38 | Complex is better than complicated.
39 | Flat is better than nested.
40 | Sparse is better than dense.
41 | Readability counts.
42 | Special cases aren't special enough to break the rules.
43 | Although practicality beats purity.
44 | Errors should never pass silently.
45 | Unless explicitly silenced.
46 | In the face of ambiguity, refuse the temptation to guess.
47 | There should be one-- and preferably only one --obvious way to do it.
48 | Although that way may not be obvious at first unless you're Dutch.
49 | Now is better than never.
50 | Although never is often better than *right* now.
51 | If the implementation is hard to explain, it's a bad idea.
52 | If the implementation is easy to explain, it may be a good idea.
53 | Namespaces are one honking great idea -- let's do more of those!
54 | ```
55 |
56 | 搜索了一下才知道这是一个 Python 的彩蛋,也被称作“Python 之禅”。
57 |
58 | 下面按照作业要求做下翻译:
59 |
60 | ```
61 | Beautiful is better than ugly.
62 | 优美胜于丑陋。
63 |
64 | Explicit is better than implicit.
65 | 明了胜于晦涩。
66 |
67 | Simple is better than complex.
68 | 简洁胜于复杂。
69 |
70 | Complex is better than complicated.
71 | 复杂胜于凌乱。
72 |
73 | Flat is better than nested.
74 | 扁平胜于嵌套。
75 |
76 | Sparse is better than dense.
77 | 间隔胜于紧凑。
78 |
79 | Readability counts.
80 | 可读性非常重要。
81 |
82 | Special cases aren't special enough to break the rules.
83 | Although practicality beats purity.
84 | 即便假借特例的实用性之名,也不可违背这些规则。
85 |
86 | Errors should never pass silently.
87 | Unless explicitly silenced.
88 | 不要包容所有错误,除非你确定需要这样做。(这里指的是异常捕获)
89 |
90 | In the face of ambiguity, refuse the temptation to guess.
91 | There should be one-- and preferably only one --obvious way to do it.
92 | 当存在多种可能,不要尝试去猜测,而是尽量找一种,最好是唯一一种明显的解决方案。
93 |
94 | Although that way may not be obvious at first unless you're Dutch.
95 | 尽管这一开始并不容易,毕竟你不是 Python 之父。
96 |
97 | Now is better than never.
98 | Although never is often better than *right* now.
99 | 做也许好过不做,但不假思索就动手还不如不做。
100 |
101 | If the implementation is hard to explain, it's a bad idea.
102 | 如果你无法向人描述你的方案,那肯定不是一个好方案。
103 |
104 | If the implementation is easy to explain, it may be a good idea.
105 | 如果你的方案易于描述,那么这可能是一个好的方案。
106 |
107 | Namespaces are one honking great idea -- let's do more of those!
108 | 命名空间是一个绝妙的理念,我们应当多加利用。
109 | ```
110 |
111 | ### 2. turtle 绘制图形
112 |
113 | turtle 是 Python 中内置的简单绘图工具,名字也很萌,叫做海龟绘图(Turtle Graphics)。
114 |
115 | 详细教程可见 [10分钟轻松学会 Python turtle 绘图](https://www.cnblogs.com/nowgood/p/turtle.html)。
116 |
117 | ```Python
118 | import turtle
119 |
120 | # 设置画笔宽度
121 | turtle.pensize(4)
122 | # 设置画笔颜色
123 | turtle.pencolor('red')
124 | # 向当前画笔方向移动 100 像素长
125 | turtle.forward(100)
126 | # 顺时针移动 90 度
127 | turtle.right(90)
128 | turtle.forward(100)
129 | turtle.right(90)
130 | turtle.forward(100)
131 | turtle.right(90)
132 | turtle.forward(100)
133 | turtle.mainloop()
134 | ```
135 |
136 | 画图结果:
137 |
138 | 
139 |
140 | ----
141 |
142 | ## 练习
143 |
144 |
--------------------------------------------------------------------------------
/day02/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 练习1:华氏温度转摄氏温度
3 | 公式:F = 1.8C + 32
4 |
5 | Version: 1.0
6 | Author: Jalan
7 | """
8 |
9 | f = float(input("请输入华氏温度:"))
10 | c = (f - 32) / 1.8
11 | print("%.1f 华氏度 = %.1f 摄氏度" % (f, c))
--------------------------------------------------------------------------------
/day02/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 练习2:输入圆的半径计算计算周长和面积
3 | 周长公式:2*pi*r
4 | 面积公式:pi*r*r
5 |
6 | Version: 1.0.0
7 | Author: Jalan
8 | """
9 |
10 | import math
11 |
12 | r = float(input("请输入圆的半径:"))
13 | perimeter = math.pi * 2 * r
14 | area = math.pi * r * r
15 |
16 | print("周长 = %.1f" % perimeter)
17 | print("面积 = %.1f" % area)
--------------------------------------------------------------------------------
/day02/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 输入年份 如果是闰年输出 True 否则输出 False
3 | 判断是否为闰年:
4 | 1. 普通闰年:能被4整除但不能被100整除的年份为普通闰年
5 | 2. 世纪闰年:能被400整除的为世纪闰年
6 |
7 | Version: 1.0.0
8 | Author: Jalan
9 | """
10 |
11 | year = int(input("请输入年份:"))
12 |
13 | is_leap = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
14 |
15 | print(is_leap)
--------------------------------------------------------------------------------
/day02/index.md:
--------------------------------------------------------------------------------
1 | # Day02 - 语言元素
2 |
3 | ## 指令和程序
4 |
5 | 计算机硬件系统的五大部件:
6 |
7 | - 运算器
8 | - 控制器
9 | - 存储器
10 | - 输入设备
11 | - 输出设备
12 |
13 | 运算器 + 控制器 = 中央处理器(CPU)
14 |
15 | 任务:复习冯·诺依曼结构。
16 |
17 | ## 变量和类型
18 |
19 | 1. 整型
20 | - 可以处理任意大小的整数(不存在溢出情况)
21 | - 支持二进制(如`0b100`,换算成十进制是4)、八进制(如`0o100`,换算成十进制是64)、十进制(`100`)和十六进制(`0x100`,换算成十进制是256)的表示法
22 | 2. 浮点型
23 | 3. 字符串型
24 | 4. 布尔型:`True` / `False`
25 | 5. 复数型
26 |
27 | ## 变量命名
28 |
29 | PER 8 要求:
30 |
31 | - 用小写字母拼写,多个单词用下划线连接
32 | - 受保护的实例属性用单个下划线开头
33 | - 私有的实例属性用两个下划线开头
34 |
35 | ## 变量强制转换
36 |
37 | - `int()`:将一个数值或字符串转换成整数,可以指定进制
38 | - `float()`:将一个字符串转换成浮点数
39 | - `str()`:将指定的对象转换成字符串形式,可以指定编码
40 | - `chr()`:将整数转换成该编码对应的字符串(一个字符)
41 | - `ord()`:将字符串(一个字符)转换成对应的编码(整数)
42 |
43 | ----
44 |
45 | ## 练习
46 |
47 | ### 练习1:华氏温度转摄氏温度
48 |
49 | ```python
50 | """
51 | 练习1:华氏温度转摄氏温度
52 | 公式:F = 1.8C + 32
53 |
54 | Version: 1.0
55 | Author: Jalan
56 | """
57 |
58 | f = float(input("请输入华氏温度:"))
59 | c = (f - 32) / 1.8
60 | print("%.1f 华氏度 = %.1f 摄氏度" % (f, c))
61 | ```
62 |
63 | 运行结果如下:
64 |
65 | ```zsh
66 | ➜ python-100-practice git:(master) ✗ /usr/local/opt/python/bin/python3.7 /Users/jalan/www/own/python-100-practice/day02/code/practice.py
67 | 请输入华氏温度:100
68 | 100.0 华氏度 = 37.8 摄氏度
69 | ```
70 |
71 | 知识点:
72 |
73 | - `input()` 接收终端参数
74 | - `float()` 强制类型转换
75 | - `print()`
76 | - 使用 `%.1f` 格式化数据为小数点后一位
77 | - `print("..." % (a, b))` 格式
78 |
79 | ### 练习2:输入圆的半径计算计算周长和面积
80 |
81 | ```python
82 | """
83 | 练习2:输入圆的半径计算计算周长和面积
84 | 周长公式:2*pi*r
85 | 面积公式:pi*r*r
86 |
87 | Version: 1.0.0
88 | Author: Jalan
89 | """
90 |
91 | import math
92 |
93 | r = float(input("请输入圆的半径:"))
94 | perimeter = math.pi * 2 * r
95 | area = math.pi * r * r
96 |
97 | print("周长 = %.1f" % perimeter)
98 | print("面积 = %.1f" % area)
99 | ```
100 |
101 | 运行结果如下:
102 |
103 | ```zsh
104 | ➜ python-100-practice git:(master) ✗ /usr/local/opt/python/bin/python3.7 /Users/jalan/www/own/python-100-practice/day02/code/practice2.py
105 | 请输入圆的半径:10
106 | 周长 = 62.8
107 | 面积 = 314.2
108 | ```
109 |
110 | 知识点:
111 |
112 | - 圆周率:`math.pi`
113 |
114 | ### 练习3:输入年份判断是不是闰年
115 |
116 | ```python
117 | """
118 | 输入年份 如果是闰年输出 True 否则输出 False
119 | 判断是否为闰年:
120 | 1. 普通闰年:能被4整除但不能被100整除的年份为普通闰年
121 | 2. 世纪闰年:能被400整除的为世纪闰年
122 |
123 | Version: 1.0.0
124 | Author: Jalan
125 | """
126 |
127 | year = int(input("请输入年份:"))
128 |
129 | is_leap = (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
130 |
131 | print(is_leap)
132 | ```
133 |
134 | 运行结果:
135 |
136 | ```zsh
137 | ➜ python-100-practice git:(master) ✗ /usr/local/opt/python/bin/python3.7 /Users/jalan/www/own/python-100-practice/day02/code/practice3.py
138 | 请输入年份:2008
139 | True
140 | ```
141 |
--------------------------------------------------------------------------------
/day03/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 英制单位英寸和公制单位厘米互换
3 | 1英寸(in) = 2.54厘米(cm)
4 |
5 | 输入:长度 value 与 单位 unit
6 | 输出:另外一类的长度与单位
7 |
8 | Version: 1.0.0
9 | Author: Jalan
10 | """
11 |
12 | value = float(input("请输入长度:"))
13 | unit = input("请输入单位:")
14 |
15 | # 如果输入的是厘米
16 | if unit == "cm" or unit == "厘米":
17 | output_value = value / 2.54
18 | print("%f 厘米 = %f 英寸" % (value, output_value))
19 | # 如果输入的是英寸
20 | elif unit == "in" or unit == "英寸":
21 | output_value = value * 2.54
22 | print("%f 英寸 = %f 厘米" % (value, output_value))
23 | # 输入的单位无效
24 | else:
25 | print("请输入有效单位")
--------------------------------------------------------------------------------
/day03/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 掷骰子决定做什么事情
3 | 摇出 1~6 的数字,判断要做什么事
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | """
8 |
9 | from random import randint
10 |
11 | # 产生 1-6 的随机数
12 | num = randint(1, 6)
13 |
14 | if num == 1:
15 | res = "吃饭"
16 | elif num == 2:
17 | res = "睡觉"
18 | elif num == 3:
19 | res = "喵喵叫"
20 | elif num == 4:
21 | res = "汪汪叫"
22 | elif num == 5:
23 | res = "打豆豆"
24 | elif num == 6:
25 | res = "写代码"
26 |
27 | print(res)
--------------------------------------------------------------------------------
/day03/code/practice2_1.py:
--------------------------------------------------------------------------------
1 | """
2 | 掷骰子决定做什么事情
3 | 摇出 1~6 的数字,判断要做什么事
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | """
8 |
9 | from random import randint
10 |
11 | d = {1: "吃饭", 2: "睡觉", 3: "喵喵叫", 4: "汪汪叫", 5: "打豆豆", 6: "写代码"}
12 | # 产生 1-6 的随机数
13 | num = randint(1, 6)
14 |
15 | print(d[num])
--------------------------------------------------------------------------------
/day03/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 百分制成绩转等级制成绩
3 | 90分以上 --> A
4 | 80分~89分 --> B
5 | 70分~79分 --> C
6 | 60分~69分 --> D
7 | 60分以下 --> E
8 |
9 | Version: 1.0.0
10 | Author: Jalan
11 | """
12 |
13 | score = float(input("请输入成绩:"))
14 |
15 | if score >= 90:
16 | grade = "A"
17 | elif score >= 80:
18 | grade = "B"
19 | elif score >= 70:
20 | grade = "C"
21 | elif score >= 60:
22 | grade = "D"
23 | else:
24 | grade = "E"
25 |
26 | print("成绩等级是:%s" % grade)
--------------------------------------------------------------------------------
/day03/code/practice4.py:
--------------------------------------------------------------------------------
1 | """
2 | 判断输入的边长能否构成三角形
3 | 如果能则计算出三角形的周长和面积
4 | 海伦公式:area = sqrt(p(p-a)(p-b)(p-c))
5 |
6 | Version: 1.0.0
7 | Author: Jalan
8 | """
9 | import math
10 |
11 | a = float(input("a = "))
12 | b = float(input("b = "))
13 | c = float(input("c = "))
14 |
15 | if a + b > c and a + c > b and b + c > a:
16 | p = a + b + c
17 | area = math.sqrt(p * (p - a) * (p - b) * (p - c))
18 | print("周长 = %.2f,面积 = %.2f" % (p, area))
19 | else:
20 | print("无法构成三角形")
--------------------------------------------------------------------------------
/day03/code/practice5.py:
--------------------------------------------------------------------------------
1 | """
2 | 输入月收入和五险一金计算个人所得税
3 |
4 | Version 1.0.0
5 | Author: Jalan
6 | """
7 |
8 | salary = float(input("本月收入:"))
9 | insurance = float(input("五险一金:"))
10 | diff = salary - insurance - 5000
11 |
12 | if diff <= 0:
13 | rate = 0
14 | deduction = 0
15 | elif diff < 3000:
16 | rate = 0.03
17 | deduction = 0
18 | elif diff < 12000:
19 | rate = 0.1
20 | deduction = 210
21 | elif diff < 25000:
22 | rate = 0.2
23 | deduction = 1410
24 | elif diff < 35000:
25 | rate = 0.25
26 | deduction = 2660
27 | elif diff < 55000:
28 | rate = 0.3
29 | deduction = 4410
30 | elif diff < 80000:
31 | rate = 0.35
32 | deduction = 7160
33 | else:
34 | rate = 0.45
35 | deduction = 15160
36 |
37 | tax = abs(diff * rate - deduction)
38 | print('个人所得税: ¥%.2f元' % tax)
39 | print('实际到手收入: ¥%.2f元' % (diff + 5000 - tax))
--------------------------------------------------------------------------------
/day03/index.md:
--------------------------------------------------------------------------------
1 | # Day03 - 分支结构
2 |
3 | - Python 中使用 `elif` 而非像别的语言那样是 `elseif`
4 | - **Flat is better than nested**:尽量减少嵌套次数
5 |
6 | ## 练习
7 |
8 | ### 练习1:英制单位与公制单位互换
9 |
10 | ```python
11 | """
12 | 英制单位英寸和公制单位厘米互换
13 | 1英寸(in) = 2.54厘米(cm)
14 |
15 | 输入:长度 value 与 单位 unit
16 | 输出:另外一类的长度与单位
17 |
18 | Version: 1.0.0
19 | Author: Jalan
20 | """
21 |
22 | value = float(input("请输入长度:"))
23 | unit = input("请输入单位:")
24 |
25 | # 如果输入的是厘米
26 | if unit == "cm" or unit == "厘米":
27 | output_value = value / 2.54
28 | print("%f 厘米 = %f 英寸" % (value, output_value))
29 | # 如果输入的是英寸
30 | elif unit == "in" or unit == "英寸":
31 | output_value = value * 2.54
32 | print("%f 英寸 = %f 厘米" % (value, output_value))
33 | # 输入的单位无效
34 | else:
35 | print("请输入有效单位")
36 | ```
37 |
38 | 注意点:判断输入的单位有效性
39 |
40 | ### 练习2:掷骰子决定做什么
41 |
42 | ```
43 | """
44 | 掷骰子决定做什么事情
45 | 摇出 1~6 的数字,判断要做什么事
46 |
47 | Version: 1.0.0
48 | Author: Jalan
49 | """
50 |
51 | from random import randint
52 |
53 | # 产生 1-6 的随机数
54 | num = randint(1, 6)
55 |
56 | if num == 1:
57 | res = "吃饭"
58 | elif num == 2:
59 | res = "睡觉"
60 | elif num == 3:
61 | res = "喵喵叫"
62 | elif num == 4:
63 | res = "汪汪叫"
64 | elif num == 5:
65 | res = "打豆豆"
66 | elif num == 6:
67 | res = "写代码"
68 |
69 | print(res)
70 | ```
71 |
72 | 知识点:使用 `random` 模块的 `randint` 函数生成特定范围的随机数。
73 |
74 | `random` 常见函数如下:
75 |
76 | ```python
77 | #!/usr/bin/python
78 | # -*- coding: UTF-8 -*-
79 |
80 | import random
81 |
82 | print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数
83 | print( random.random() ) # 产生 0 到 1 之间的随机浮点数
84 | print( random.uniform(1.1,5.4) ) # 产生 1.1 到 5.4 之间的随机浮点数,区间可以不是整数
85 | print( random.choice('tomorrow') ) # 从序列中随机选取一个元素
86 | print( random.randrange(1,100,2) ) # 生成从1到100的间隔为2的随机整数
87 |
88 | a=[1,3,5,6,7] # 将序列a中的元素顺序打乱
89 | random.shuffle(a)
90 | print(a)
91 | ```
92 |
93 | 这道题如果不属于分支结构分类的话,我可能会用字典来写:
94 |
95 | ```python
96 | """
97 | 掷骰子决定做什么事情
98 | 摇出 1~6 的数字,判断要做什么事
99 |
100 | Version: 1.0.0
101 | Author: Jalan
102 | """
103 |
104 | from random import randint
105 |
106 | d = {1: "吃饭", 2: "睡觉", 3: "喵喵叫", 4: "汪汪叫", 5: "打豆豆", 6: "写代码"}
107 | # 产生 1-6 的随机数
108 | num = randint(1, 6)
109 |
110 | print(d[num])
111 | ```
112 |
113 | ### 练习3:百分制成绩转等级制
114 |
115 | ```python
116 | """
117 | 百分制成绩转等级制成绩
118 | 90分以上 --> A
119 | 80分~89分 --> B
120 | 70分~79分 --> C
121 | 60分~69分 --> D
122 | 60分以下 --> E
123 |
124 | Version: 1.0.0
125 | Author: Jalan
126 | """
127 |
128 | score = float(input("请输入成绩:"))
129 |
130 | if score >= 90:
131 | grade = "A"
132 | elif score >= 80:
133 | grade = "B"
134 | elif score >= 70:
135 | grade = "C"
136 | elif score >= 60:
137 | grade = "D"
138 | else:
139 | grade = "E"
140 |
141 | print("成绩等级是:%s" % grade)
142 | ```
143 |
144 | ### 练习4:输入三条边长如果能构成三角形就计算周长和面积
145 |
146 | ```python
147 | """
148 | 判断输入的边长能否构成三角形
149 | 如果能则计算出三角形的周长和面积
150 | 海伦公式:area = sqrt(p(p-a)(p-b)(p-c))
151 |
152 | Version: 1.0.0
153 | Author: Jalan
154 | """
155 | import math
156 |
157 | a = float(input("a = "))
158 | b = float(input("b = "))
159 | c = float(input("c = "))
160 |
161 | if a + b > c and a + c > b and b + c > a:
162 | p = a + b + c
163 | area = math.sqrt(p * (p - a) * (p - b) * (p - c))
164 | print("周长 = %.2f,面积 = %.2f" % (p, area))
165 | else:
166 | print("无法构成三角形")
167 | ```
168 |
169 | 完全忘记三角形面积怎么算了……😓然后复习了海伦公式……
170 |
171 | ### 练习5:个人所得税计算器
172 |
173 | ```python
174 | """
175 | 输入月收入和五险一金计算个人所得税
176 |
177 | Version 1.0.0
178 | Author: Jalan
179 | """
180 |
181 | salary = float(input("本月收入:"))
182 | insurance = float(input("五险一金:"))
183 | diff = salary - insurance - 5000
184 |
185 | if diff <= 0:
186 | rate = 0
187 | deduction = 0
188 | elif diff < 3000:
189 | rate = 0.03
190 | deduction = 0
191 | elif diff < 12000:
192 | rate = 0.1
193 | deduction = 210
194 | elif diff < 25000:
195 | rate = 0.2
196 | deduction = 1410
197 | elif diff < 35000:
198 | rate = 0.25
199 | deduction = 2660
200 | elif diff < 55000:
201 | rate = 0.3
202 | deduction = 4410
203 | elif diff < 80000:
204 | rate = 0.35
205 | deduction = 7160
206 | else:
207 | rate = 0.45
208 | deduction = 15160
209 |
210 | tax = abs(diff * rate - deduction)
211 | print('个人所得税: ¥%.2f元' % tax)
212 | print('实际到手收入: ¥%.2f元' % (diff + 5000 - tax))
213 | ```
214 |
215 | 个税表可以参考:[2018年新版个税计算器(5000起征点)](http://www.chineseacc.com/tool/gsjsq/2018-07-31/2923.html)
216 |
217 | 知识点:`abs()` 用于处理 `-0` 的问题
--------------------------------------------------------------------------------
/day04/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 输入一个正整数判断它是不是素数
3 | 素数:只能被 1 和它本身整除的数(1 不是素数)
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | Date: 2019-05-21
8 | """
9 |
10 | import math
11 |
12 | num = int(input("请输入一个整数:"))
13 | end = int(math.sqrt(num))
14 |
15 | is_prime = True
16 | for i in range(2, end + 1):
17 | if num % i == 0:
18 | is_prime = False
19 | break
20 |
21 | if is_prime and num != 1:
22 | print("%d 是素数" % num)
23 | else:
24 | print("%d 不是素数" % num)
--------------------------------------------------------------------------------
/day04/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 输入两个正整数计算最大公约数和最小公倍数
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-21
7 | """
8 |
9 | x = int(input("x = "))
10 | y = int(input("y = "))
11 |
12 | if x > y:
13 | x, y = y, x
14 |
15 | for factor in range(x, 0, -1):
16 | if x % factor == 0 and y % factor == 0:
17 | print("%d 和 %d 的最大公约数为 %d" % (x, y, factor))
18 | print("%d 和 %d 的最小公倍为 %d" % (x, y, x * y // factor))
19 | break
--------------------------------------------------------------------------------
/day04/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 打印各种三角形图案
3 |
4 | *
5 | **
6 | ***
7 | ****
8 | *****
9 |
10 | *
11 | **
12 | ***
13 | ****
14 | *****
15 |
16 | *
17 | ***
18 | *****
19 | *******
20 | *********
21 |
22 | Version: 0.1
23 | Author: Jalan
24 | Date: 2019-05-21
25 | """
26 |
27 | row = int(input("请输入行数:"))
28 |
29 | # 第一种三角形:第 x 行打印出 x 个星号
30 | for i in range(row):
31 | for _ in range(i + 1):
32 | print("*", end="")
33 | print()
34 |
35 | # 第二种三角形:第 x 行打印 row - x 个空格和 x 个星号
36 | for i in range(row):
37 | row_num = i + 1
38 | space = row - row_num
39 |
40 | for _ in range(space):
41 | print(" ", end="")
42 |
43 | for _ in range(row_num):
44 | print("*", end="")
45 |
46 | print()
47 |
48 | # 第三种三角形:每一行的星号数量是 1, 3, 5, 7, 9......
49 |
50 | # 最后一行星号数量
51 | max_num = 2 * row - 1
52 |
53 | for i in range(row):
54 | row_num = i + 1
55 | # 当前行星号数量
56 | star_num = row_num * 2 - 1
57 | # 当前行左右分别存在空格数量
58 | space = int((max_num - star_num) / 2)
59 |
60 | for _ in range(space):
61 | print(" ", end="")
62 |
63 | for _ in range(star_num):
64 | print("*", end="")
65 |
66 | print()
--------------------------------------------------------------------------------
/day04/index.md:
--------------------------------------------------------------------------------
1 | # Day04 - 循环结构
2 |
3 | - `for-in`:明确的知道循环执行的次数或者是要对一个容器进行迭代
4 | - `while`:不知道具体循环次
5 | - [range() 函数用法](https://www.runoob.com/python/python-func-range.html)
6 |
7 | ## 练习
8 |
9 | ### 练习1:输入一个数判断是不是素数
10 |
11 | ```python
12 | """
13 | 输入一个正整数判断它是不是素数
14 | 素数:只能被 1 和它本身整除的数(1 不是素数)
15 |
16 | Version: 1.0.0
17 | Author: Jalan
18 | Date: 2019-05-21
19 | """
20 |
21 | import math
22 |
23 | num = int(input("请输入一个整数:"))
24 | end = int(math.sqrt(num))
25 |
26 | is_prime = True
27 | for i in range(2, end + 1):
28 | if num % i == 0:
29 | is_prime = False
30 | break
31 |
32 | if is_prime and num != 1:
33 | print("%d 是素数" % num)
34 | else:
35 | print("%d 不是素数" % num)
36 | ```
37 |
38 | ### 练习2:输入两个正整数,计算最大公约数和最小公倍数
39 |
40 | ```python
41 | """
42 | 输入两个正整数计算最大公约数和最小公倍数
43 |
44 | Version: 1.0.0
45 | Author: Jalan
46 | Date: 2019-05-21
47 | """
48 |
49 | x = int(input("x = "))
50 | y = int(input("y = "))
51 |
52 | if x > y:
53 | x, y = y, x
54 |
55 | for factor in range(x, 0, -1):
56 | if x % factor == 0 and y % factor == 0:
57 | print("%d 和 %d 的最大公约数为 %d" % (x, y, factor))
58 | print("%d 和 %d 的最小公倍为 %d" % (x, y, x * y // factor))
59 | break
60 | ```
61 |
62 | 知识点:
63 |
64 | - 最大公约数和最小公倍数的求法(???😓)
65 | - 学习了新的方法 `range(x, 0, -1)`,之前如果要反序的话我一般会用 `reversed(range(0, x + 1))`
66 |
67 | ### 练习3:打印三角形图案
68 |
69 | ```python
70 | """
71 | 打印各种三角形图案
72 |
73 | *
74 | **
75 | ***
76 | ****
77 | *****
78 |
79 | *
80 | **
81 | ***
82 | ****
83 | *****
84 |
85 | *
86 | ***
87 | *****
88 | *******
89 | *********
90 |
91 | Version: 0.1
92 | Author: Jalan
93 | Date: 2019-05-21
94 | """
95 |
96 | row = int(input("请输入行数:"))
97 |
98 | # 第一种三角形:第 x 行打印出 x 个星号
99 | for i in range(row):
100 | for _ in range(i + 1):
101 | print("*", end="")
102 | print()
103 |
104 | # 第二种三角形:第 x 行打印 row - x 个空格和 x 个星号
105 | for i in range(row):
106 | row_num = i + 1
107 | space = row - row_num
108 |
109 | for _ in range(space):
110 | print(" ", end="")
111 |
112 | for _ in range(row_num):
113 | print("*", end="")
114 |
115 | print()
116 |
117 | # 第三种三角形:每一行的星号数量是 1, 3, 5, 7, 9......
118 |
119 | # 最后一行星号数量
120 | max_num = 2 * row - 1
121 |
122 | for i in range(row):
123 | row_num = i + 1
124 | # 当前行星号数量
125 | star_num = row_num * 2 - 1
126 | # 当前行左右分别存在空格数量
127 | space = int((max_num - star_num) / 2)
128 |
129 | for _ in range(space):
130 | print(" ", end="")
131 |
132 | for _ in range(star_num):
133 | print("*", end="")
134 |
135 | for _ in range(space):
136 | print(" ", end="")
137 |
138 | print()
139 | ```
140 |
141 | ```
142 | *
143 | ***
144 | *****
145 | *******
146 | *********
147 | ```
148 |
149 | 打印第三种三角形👆的时候,我分了前、中、后三段进行打印。后面看了骆昊老师的代码:
150 |
151 | ```python
152 | for i in range(row):
153 | for _ in range(row - i - 1):
154 | print(' ', end='')
155 | for _ in range(2 * i + 1):
156 | print('*', end='')
157 | print()
158 | ```
159 |
160 | 第三段的空格根本不用打嘛,傻了傻了🤦♂……
161 |
--------------------------------------------------------------------------------
/day05/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 找出100~999之间的所有水仙花数
3 | 水仙花数是各位立方和等于这个数本身的数
4 | 如: 153 = 1**3 + 5**3 + 3**3
5 |
6 | Version: 1.0.0
7 | Author: Jalan
8 | Date: 2019-05-22
9 | """
10 |
11 | res = []
12 | for num in range(100, 1000):
13 | tmp = num
14 | c = tmp % 10
15 | tmp //= 10
16 | b = tmp % 10
17 | tmp //= 10
18 | a = tmp % 10
19 | if num == a**3 + b**3 + c**3:
20 | # 转为 string 类型,否则 join 会报错
21 | res.append(str(num))
22 | res_string = ", ".join(res)
23 | print("水仙花数有:%s" % res_string)
--------------------------------------------------------------------------------
/day05/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 完美数是除自身外其他所有因子的和正好等于这个数本身的数
3 | 来自 LeetCode: 507. 完美数
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | Date: 2019-05-22
8 | """
9 |
10 | import math
11 |
12 | class Solution(object):
13 | def checkPerfectNumber(self, num):
14 | """
15 | :type num: int
16 | :rtype: bool
17 | """
18 |
19 | if num <= 1:
20 | return False
21 |
22 | s = 0
23 | for factor in range(1, int(math.sqrt(num)) + 1):
24 | # 判断是否是因子
25 | if num % factor == 0:
26 | s += factor
27 | # 避免相同因子重复添加
28 | if factor != 1 and num / factor != factor:
29 | s += num / factor
30 |
31 | if s == num:
32 | return True
33 | else:
34 | return False
--------------------------------------------------------------------------------
/day05/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 求解《百钱百鸡》问题
3 | 1 只公鸡 5 元 1 只母鸡 3 元 3 只小鸡 1 元 用 100 元买 100 只鸡
4 | 问公鸡 母鸡 小鸡各有多少只
5 |
6 | Version: 1.0.0
7 | Author: Jalan
8 | Date: 2019-05-22
9 | """
10 |
11 | for x in range(0, 20):
12 | for y in range(0, 33):
13 | z = 100 - x - y
14 | if 5 * x + 3 * y + z /3 == 100:
15 | print("公鸡 %d, 母鸡 %d, 小鸡 %d" % (x, y, z))
--------------------------------------------------------------------------------
/day05/code/practice4.py:
--------------------------------------------------------------------------------
1 | """
2 | 输出斐波那契数列的前20个数
3 | 1 1 2 3 5 8 13 21 ...
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | Date: 2019-05-22
8 | """
9 |
10 | a = 1
11 | b = 1
12 | for i in range(20):
13 | print("%d " % a, end="")
14 | a , b = b, a + b
15 |
--------------------------------------------------------------------------------
/day05/code/practice5.py:
--------------------------------------------------------------------------------
1 | """
2 | Craps赌博游戏
3 | 玩家摇两颗色子 如果第一次摇出7点或11点 玩家胜
4 | 如果摇出2点 3点 12点 庄家胜 其他情况游戏继续
5 | 玩家再次要色子 如果摇出7点 庄家胜
6 | 如果摇出第一次摇的点数 玩家胜
7 | 否则游戏继续 玩家继续摇色子
8 | 玩家进入游戏时有1000元的赌注 全部输光游戏结束
9 |
10 | Version: 1.0.0
11 | Author: Jalan
12 | Date: 2019-05-22
13 | """
14 | import random
15 |
16 | def get_random_num():
17 | num = random.randint(1, 6) + random.randint(1, 6)
18 | print("摇骰子点数为 %d" % num)
19 | return num
20 |
21 | money = 1000
22 | count = 1
23 |
24 | while money > 0:
25 | print("第 %d 局开始,您的赌注为 %d 元" % (count, money))
26 |
27 | while True:
28 | debt = int(input('请下注: '))
29 | if debt > 0 and debt <= money:
30 | break
31 |
32 | first_num = get_random_num()
33 | if first_num == 7 or first_num == 11:
34 | money += debt
35 | print("本轮结束,玩家胜")
36 | elif first_num == 2 or first_num == 3 or first_num == 12:
37 | money -= debt
38 | print("本轮结束,庄家胜")
39 | else:
40 | second_num = get_random_num()
41 | if second_num == 7:
42 | money -= debt
43 | print("本轮结束,庄家胜")
44 | elif second_num == first_num:
45 | money += debt
46 | print("本轮结束,玩家胜")
47 | else:
48 | print("本轮结束,未分出胜负")
49 |
50 | count += 1
51 |
52 | print("游戏结束,您身无分文")
53 |
54 |
55 |
--------------------------------------------------------------------------------
/day05/index.md:
--------------------------------------------------------------------------------
1 | # Day05 - 练习
2 |
3 | ## 1. 寻找水仙花数
4 |
5 | ```python
6 | """
7 | 找出100~999之间的所有水仙花数
8 | 水仙花数是各位立方和等于这个数本身的数
9 | 如: 153 = 1**3 + 5**3 + 3**3
10 |
11 | Version: 1.0.0
12 | Author: Jalan
13 | Date: 2019-05-22
14 | """
15 |
16 | res = []
17 | for num in range(100, 1000):
18 | tmp = num
19 | c = tmp % 10
20 | tmp //= 10
21 | b = tmp % 10
22 | tmp //= 10
23 | a = tmp % 10
24 | if num == a**3 + b**3 + c**3:
25 | # 转为 string 类型,否则 join 会报错
26 | res.append(str(num))
27 | res_string = ", ".join(res)
28 | print("水仙花数有:%s" % res_string)
29 | ```
30 |
31 | ## 2. 寻找完美数
32 |
33 | [LeetCode 507. 完美数](https://leetcode-cn.com/problems/perfect-number/)
34 |
35 | ```python
36 | """
37 | 完美数是除自身外其他所有因子的和正好等于这个数本身的数
38 | 来自 LeetCode: 507. 完美数
39 |
40 | Version: 1.0.0
41 | Author: Jalan
42 | Date: 2019-05-22
43 | """
44 |
45 | import math
46 |
47 | class Solution(object):
48 | def checkPerfectNumber(self, num):
49 | """
50 | :type num: int
51 | :rtype: bool
52 | """
53 |
54 | if num <= 1:
55 | return False
56 |
57 | s = 0
58 | for factor in range(1, int(math.sqrt(num)) + 1):
59 | # 判断是否是因子
60 | if num % factor == 0:
61 | s += factor
62 | # 避免相同因子重复添加
63 | if factor != 1 and num / factor != factor:
64 | s += num / factor
65 |
66 | if s == num:
67 | return True
68 | else:
69 | return False
70 | ```
71 |
72 | ## 3. 百钱百🐔
73 |
74 | 模拟就对了。
75 |
76 | ```python
77 | """
78 | 求解《百钱百鸡》问题
79 | 1 只公鸡 5 元 1 只母鸡 3 元 3 只小鸡 1 元 用 100 元买 100 只鸡
80 | 问公鸡 母鸡 小鸡各有多少只
81 |
82 | Version: 1.0.0
83 | Author: Jalan
84 | Date: 2019-05-22
85 | """
86 |
87 | for x in range(0, 20):
88 | for y in range(0, 33):
89 | z = 100 - x - y
90 | if 5 * x + 3 * y + z /3 == 100:
91 | print("公鸡 %d, 母鸡 %d, 小鸡 %d" % (x, y, z))
92 | ```
93 |
94 | ## 4. 生成斐波拉切数列
95 |
96 | ```python
97 | """
98 | 输出斐波那契数列的前20个数
99 | 1 1 2 3 5 8 13 21 ...
100 |
101 | Version: 1.0.0
102 | Author: Jalan
103 | Date: 2019-05-22
104 | """
105 |
106 | a = 1
107 | b = 1
108 | for i in range(20):
109 | print("%d " % a, end="")
110 | a , b = b, a + b
111 |
112 | ```
113 |
114 | ## 5. Craps赌博游戏
115 |
116 | ```python
117 | """
118 | Craps赌博游戏
119 | 玩家摇两颗色子 如果第一次摇出7点或11点 玩家胜
120 | 如果摇出2点 3点 12点 庄家胜 其他情况游戏继续
121 | 玩家再次要色子 如果摇出7点 庄家胜
122 | 如果摇出第一次摇的点数 玩家胜
123 | 否则游戏继续 玩家继续摇色子
124 | 玩家进入游戏时有1000元的赌注 全部输光游戏结束
125 |
126 | Version: 1.0.0
127 | Author: Jalan
128 | Date: 2019-05-22
129 | """
130 | import random
131 |
132 | def get_random_num():
133 | num = random.randint(1, 6) + random.randint(1, 6)
134 | print("摇骰子点数为 %d" % num)
135 | return num
136 |
137 | money = 1000
138 | count = 1
139 |
140 | while money > 0:
141 | print("第 %d 局开始,您的赌注为 %d 元" % (count, money))
142 |
143 | while True:
144 | debt = int(input('请下注: '))
145 | if debt > 0 and debt <= money:
146 | break
147 |
148 | first_num = get_random_num()
149 | if first_num == 7 or first_num == 11:
150 | money += debt
151 | print("本轮结束,玩家胜")
152 | elif first_num == 2 or first_num == 3 or first_num == 12:
153 | money -= debt
154 | print("本轮结束,庄家胜")
155 | else:
156 | second_num = get_random_num()
157 | if second_num == 7:
158 | money -= debt
159 | print("本轮结束,庄家胜")
160 | elif second_num == first_num:
161 | money += debt
162 | print("本轮结束,玩家胜")
163 | else:
164 | print("本轮结束,未分出胜负")
165 |
166 | count += 1
167 |
168 | print("游戏结束,您身无分文")
169 | ```
170 |
171 | 写完发现还挺好玩的……
--------------------------------------------------------------------------------
/day06/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 实现计算求最大公约数和最小公倍数的函数
3 |
4 | Version: 1.0.0
5 | Authro: Jalan
6 | Date: 2019-05-22
7 | """
8 | # 求最大公约数
9 | def gcd(x, y):
10 | if x > y:
11 | x, y = y, x
12 | for factor in range(x, 0, -1):
13 | if x % factor == 0 and y % factor == 0:
14 | return factor
15 |
16 | # 求最小公倍数
17 | def lcm(x, y):
18 | return x * y // gcd(x, y)
--------------------------------------------------------------------------------
/day06/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 判断一个数是不是回文数的函数
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-22
7 | """
8 |
9 | def is_palindrome(num):
10 | num_string = str(num)
11 | i = 0
12 | j = len(num_string) - 1
13 |
14 | while i <= j:
15 | left = num_string[i]
16 | right = num_string[j]
17 | if left != right:
18 | return False
19 | i += 1
20 | j -= 1
21 |
22 | return True
23 |
24 | n = int(input("输入数字:"))
25 | print(is_palindrome(n))
--------------------------------------------------------------------------------
/day06/code/practice2_1.py:
--------------------------------------------------------------------------------
1 | """
2 | 判断一个数是不是回文数的函数
3 |
4 | Version: 2.0.0
5 | Author: Jalan
6 | Date: 2019-05-22
7 | """
8 |
9 | def is_palindrome(num):
10 | temp = num
11 | total = 0
12 |
13 | while temp > 0:
14 | total = total * 10 + temp % 10
15 | temp //= 10
16 | return total == temp
17 |
18 | n = int(input("输入数字:"))
19 | print(is_palindrome(n))
--------------------------------------------------------------------------------
/day06/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 实现判断一个数是不是素数的函数
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-22
7 | """
8 | from math import sqrt
9 |
10 | def is_prime(num):
11 | for i in range(2, int(sqrt(num)) + 1):
12 | if num % i == 0:
13 | return False
14 | return True if num != 1 else False
15 |
16 | n = int(input("输入 n:"))
17 | print(is_prime(n))
--------------------------------------------------------------------------------
/day06/index.md:
--------------------------------------------------------------------------------
1 | # Day06 - 函数和模块的使用
2 |
3 | ## 定义函数
4 |
5 | - `def` 关键字声明(和别的语言不太一样,PHP 是 `function`,Go 是 `func`)
6 | - 函数名也采用小写字母 + 下划线方式:`xxx_yyy`
7 | - `return` 关键字返回值
8 |
9 | ## 函数的参数
10 |
11 | - 有默认值
12 | - 支持可变参数(`*args`)
13 | - 传参可指定顺序
14 |
15 | 因此 Python 不支持 [函数重载](https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BD)。
16 |
17 | [为什么 Python 不支持函数重载?其他函数大部分都支持的?](https://www.zhihu.com/question/20053359)
18 |
19 | ## 用模块管理函数
20 |
21 | - 模块用于解决命名冲突问题(类似 PHP 中的命名空间)
22 | - 每个文件就是代表一个模块(module)
23 |
24 | 几种写法:
25 |
26 | ```python
27 | from module1 import foo
28 |
29 | foo()
30 | ```
31 |
32 | ```python
33 | import module1 as m1
34 |
35 | m1.foo()
36 | ```
37 |
38 | ```python
39 | import modeul1 import foo
40 |
41 | foo()
42 | ```
43 |
44 | 如果导入的模块除了定义函数之外还中有可以执行代码,那么 Python 解释器在导入这个模块时就会执行这些代码。
45 |
46 | 处理方式:将其余代码放入 `if __name__ == "__main__"` 条件中,只有直接执行的模块名字才叫做 `__main__`。
47 |
48 | ```python
49 | def foo():
50 | pass
51 |
52 |
53 | def bar():
54 | pass
55 |
56 |
57 | # __name__是Python中一个隐含的变量它代表了模块的名字
58 | # 只有被Python解释器直接执行的模块的名字才是__main__
59 | if __name__ == '__main__':
60 | print('call foo()')
61 | foo()
62 | print('call bar()')
63 | bar()
64 | ```
65 |
66 | ### 变量作用域
67 |
68 | - 没有定义在任何函数中的变量是全局变量(global variable)
69 | - 定义在函数中的变量是局部变量(local variable)
70 | - 变量查找顺序
71 | 1. 局部作用域
72 | 2. 嵌套作用域
73 | 3. 全局作用域
74 | 4. 内置作用域(内置的 `len` / `min` 等隐含标识)
75 |
76 | 如果要在函数内部修改全局变量,需要使用 `global` 关键字来指示变量来自于全局作用域:
77 |
78 | ```python
79 | def foo():
80 | global a
81 | a = 200
82 | print(a) # 200
83 |
84 |
85 | if __name__ == '__main__':
86 | a = 100
87 | foo()
88 | print(a) # 200
89 | ```
90 |
91 | 同理,使用 `nonlocal` 关键字可以指示嵌套作用域。
92 |
93 | ## 练习
94 |
95 | ### 练习1:实现计算求最大公约数和最小公倍数的函数
96 |
97 | ```python
98 | """
99 | 实现计算求最大公约数和最小公倍数的函数
100 |
101 | Version: 1.0.0
102 | Authro: Jalan
103 | Date: 2019-05-22
104 | """
105 | # 求最大公约数
106 | def gcd(x, y):
107 | if x > y:
108 | x, y = y, x
109 | for factor in range(x, 0, -1):
110 | if x % factor == 0 and y % factor == 0:
111 | return factor
112 |
113 | # 求最小公倍数
114 | def lcm(x, y):
115 | return x * y // gcd(x, y)
116 | ```
117 |
118 | ### 练习2:实现判断一个数是不是回文数的函数
119 |
120 | #### 解法一
121 |
122 | 用了双指针来做。
123 |
124 | ```python
125 | """
126 | 判断一个数是不是回文数的函数
127 |
128 | Version: 1.0.0
129 | Author: Jalan
130 | Date: 2019-05-22
131 | """
132 |
133 | def is_palindrome(num):
134 | num_string = str(num)
135 | i = 0
136 | j = len(num_string) - 1
137 |
138 | while i <= j:
139 | left = num_string[i]
140 | right = num_string[j]
141 | if left != right:
142 | return False
143 | i += 1
144 | j -= 1
145 |
146 | return True
147 |
148 | n = int(input("输入数字:"))
149 | print(is_palindrome(n))
150 | ```
151 |
152 | #### 解法二
153 |
154 | 求 `num` 反序数字再比较。
155 |
156 | ```python
157 | """
158 | 判断一个数是不是回文数的函数
159 |
160 | Version: 2.0.0
161 | Author: Jalan
162 | Date: 2019-05-22
163 | """
164 |
165 | def is_palindrome(num):
166 | temp = num
167 | total = 0
168 |
169 | while temp > 0:
170 | total = total * 10 + temp % 10
171 | temp //= 10
172 | # 甚至想写一个条件结构,感觉有的时候自己写代码还是太啰嗦了……
173 | return total == temp
174 |
175 | n = int(input("输入数字:"))
176 | print(is_palindrome(n))
177 | ```
178 |
179 | ### 练习3:实现判断一个数是不是素数的函数
180 |
181 | ```python
182 | """
183 | 实现判断一个数是不是素数的函数
184 |
185 | Version: 1.0.0
186 | Author: Jalan
187 | Date: 2019-05-22
188 | """
189 | from math import sqrt
190 |
191 | def is_prime(num):
192 | for i in range(2, int(sqrt(num)) + 1):
193 | if num % i == 0:
194 | return False
195 | return True if num != 1 else False
196 |
197 | n = int(input("输入 n:"))
198 | print(is_prime(n))
199 | ```
200 |
201 | 知识点:`return True if num != 1 else False` 简洁写法
202 |
203 | ### 练习4:写一个程序判断输入的正整数是不是回文素数
204 |
205 | 利用上面练习写好的函数就好了。
206 |
207 | ```python
208 | if __name__ == '__main__':
209 | num = int(input('请输入正整数: '))
210 | if is_palindrome(num) and is_prime(num):
211 | print('%d是回文素数' % num)
212 | ```
--------------------------------------------------------------------------------
/day07/code/case1.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/day07/code/case1.py
--------------------------------------------------------------------------------
/day07/code/case2.py:
--------------------------------------------------------------------------------
1 | """
2 | 约瑟夫问题
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | def main():
10 | # 初始化,还没被扔掉的标为 True
11 | persons = [True for _ in range(30)]
12 | count, index, number = 0, 0, 0
13 | while count < 15:
14 | if persons[index]:
15 | number += 1 # 计数
16 | if number == 9:
17 | # 被扔掉
18 | persons[index] = False
19 | # 扔掉的人数 + 1
20 | count += 1
21 | # 重新开始计数
22 | number = 0
23 | index += 1
24 | index %= 30
25 |
26 | for person in persons:
27 | print('是基督徒' if person else '不是基督徒')
28 |
29 | if __name__ == "__main__":
30 | main()
--------------------------------------------------------------------------------
/day07/code/case3.py:
--------------------------------------------------------------------------------
1 | """
2 | 井字棋
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | import os
10 |
11 | def print_board(board):
12 | """
13 | 画格子
14 |
15 | :param board: 每个格子的内容
16 | """
17 | print(board['TL'] + '|' + board['TM'] + '|' + board['TR'])
18 | print('-+-+-')
19 | print(board['ML'] + '|' + board['MM'] + '|' + board['MR'])
20 | print('-+-+-')
21 | print(board['BL'] + '|' + board['BM'] + '|' + board['BR'])
22 |
23 | def is_winner(board, turn):
24 | """
25 | 判断走棋者是否是赢家
26 |
27 | :param board: 当前棋盘数据
28 | :param turn: 走棋者
29 | :return 走棋者是赢家返回 True,否则返回 False
30 | """
31 | return ((board['TL'] == turn and board['TM'] == turn and board['TR'] == turn) or
32 | (board['ML'] == turn and board['MM'] == turn and board['MR'] == turn) or
33 | (board['BL'] == turn and board['BM'] == turn and board['BR'] == turn) or
34 | (board['TL'] == turn and board['ML'] == turn and board['BL'] == turn) or
35 | (board['TM'] == turn and board['MM'] == turn and board['BM'] == turn) or
36 | (board['TR'] == turn and board['MR'] == turn and board['BR'] == turn) or
37 | (board['TL'] == turn and board['MM'] == turn and board['BR'] == turn) or
38 | (board['BL'] == turn and board['MM'] == turn and board['TR'] == turn))
39 |
40 | def main():
41 | # 初始化一个空棋盘
42 | init_board = {
43 | 'TL': ' ', 'TM': ' ', 'TR': ' ',
44 | 'ML': ' ', 'MM': ' ', 'MR': ' ',
45 | 'BL': ' ', 'BM': ' ', 'BR': ' '
46 | }
47 | # print_board(init_board)
48 |
49 | begin = True
50 |
51 | while begin:
52 | # 开始一盘新棋局
53 | current_board = init_board.copy()
54 | begin = False
55 |
56 | # 轮到 x 走
57 | turn = 'x'
58 | # 已经走了几个格子
59 | counter = 0
60 |
61 | # 清屏
62 | os.system('clear')
63 |
64 | print_board(current_board)
65 |
66 | while counter < 9:
67 | move = input('轮到 %s 走,请输入位置:' % turn)
68 | if current_board[move] == ' ':
69 | counter += 1
70 | current_board[move] = turn
71 |
72 | if is_winner(current_board, turn):
73 | print("产生赢家:%s 赢得胜利" % turn)
74 | break
75 |
76 | turn = 'o' if turn == 'x' else 'x'
77 |
78 | os.system('clear')
79 | print_board(current_board)
80 |
81 | choice = input('是否再玩一局?(y/n)')
82 | begin = choice == 'y'
83 |
84 |
85 | if __name__ == "__main__":
86 | main()
--------------------------------------------------------------------------------
/day07/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 在屏幕上显示跑马灯文字
3 | 打印一段文字,休眠,清理屏幕,打印……
4 |
5 | Version: 1.0.0
6 | Author: Jalan
7 | Date: 2019-05-23
8 | """
9 | import os
10 | import time
11 |
12 | def main():
13 | content = "今天是个好日子啊……"
14 | while True:
15 | os.system('clear')
16 | print(content)
17 |
18 | # 休眠
19 | time.sleep(0.2)
20 | # 制造跑马灯效果
21 | content = content[1:] + content[0]
22 |
23 | if __name__ == "__main__":
24 | main()
--------------------------------------------------------------------------------
/day07/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 | import random
9 |
10 | def generate_code(code_length=4):
11 | """
12 | 生成指定长度的验证码
13 |
14 | :param code_len: 验证码长度(默认 4 个字符)
15 |
16 | :return: 由大小写英文字母和数字构成的随机验证码
17 | """
18 | # 大写字母
19 | upper_list = [chr(x) for x in range(ord('A'), ord('A') + 26)]
20 | #print(upper_list)
21 | # 小写字母
22 | lower_list = [chr(x) for x in range(ord('a'), ord('a') + 26)]
23 | #print(lower_list)
24 | # 0-9 数字
25 | digit_list = [x for x in range(0, 10)]
26 | #print(digit_list)
27 | res_list = upper_list + lower_list + digit_list
28 | res_list_len = len(res_list)
29 | code = ''
30 | for _ in range(code_length):
31 | index = random.randint(0, res_list_len - 1)
32 | code += res_list[index]
33 | return code
34 |
35 | def main():
36 | code_len = int(input('请输入验证码长度:'))
37 | print(generate_code(code_len))
38 |
39 | if __name__ == '__main__':
40 | main()
--------------------------------------------------------------------------------
/day07/code/practice3.py:
--------------------------------------------------------------------------------
1 | """
2 | 设计一个函数返回给定文件名的后缀名
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | def get_suffix(filename, has_dot=True):
10 | """
11 | 获取文件名后缀
12 |
13 | :param filename: 文件名
14 | :param has_dot: 后缀是否需要带点
15 | :return: 文件名后缀
16 | """
17 | pos = filename.rfind('.')
18 | if pos != -1:
19 | index = pos if has_dot else pos + 1
20 | return filename[index:]
21 | else:
22 | return ''
23 |
24 | def main():
25 | filename = str(input('输入文件名:'))
26 | print(get_suffix(filename, False))
27 |
28 | if __name__ == '__main__':
29 | main()
30 |
--------------------------------------------------------------------------------
/day07/code/practice4.py:
--------------------------------------------------------------------------------
1 | """
2 | 练习4:设计一个函数返回传入的列表中最大和第二大的元素的值
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | def get_top2_element(element_list):
10 | """
11 | 返回传入列表最大和第二大元素的值
12 |
13 | :param element_list: 传入列表
14 | :return 最大和第二大元素
15 | """
16 | element_list.sort(reverse=True)
17 | return element_list[:2]
18 |
19 | def main():
20 | element_list = [2, 5, 10, 22]
21 | print(get_top2_element(element_list))
22 |
23 | if __name__ == '__main__':
24 | main()
--------------------------------------------------------------------------------
/day07/code/practice5.py:
--------------------------------------------------------------------------------
1 | """
2 | 练习5:计算指定的年月日是这一年的第几天
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | def is_leap_year(year):
10 | """
11 | 判断是否是闰年
12 |
13 | :param year: 年
14 | :return 闰年返回 True,非闰年返回 False
15 | """
16 | return year % 4 == 0 and year % 100 != 0 or year % 400 == 0
17 |
18 | def which_day(year, month, day):
19 | """
20 | 返回指定的年月日是这一年的第几天
21 |
22 | :param year: 年
23 | :param month: 月
24 | :param day: 日
25 | :return 第几天
26 | """
27 | month_day = {
28 | 1: 31,
29 | 2: 28,
30 | 3: 31,
31 | 4: 30,
32 | 5: 31,
33 | 6: 30,
34 | 7: 31,
35 | 8: 31,
36 | 9: 30,
37 | 10: 31,
38 | 11: 30,
39 | 12: 31
40 | }
41 |
42 | # 闰年
43 | if is_leap_year:
44 | month_day[2] = 29
45 |
46 | day_count = 0
47 | for i in range(1, month):
48 | day_count += month_day[i]
49 | day_count += day
50 |
51 | return day_count
52 |
53 |
54 | def main():
55 | print(which_day(2019, 5, 23))
56 |
57 | if __name__ == '__main__':
58 | main()
59 |
--------------------------------------------------------------------------------
/day07/code/practice6.py:
--------------------------------------------------------------------------------
1 | """
2 | 练习6:打印杨辉三角
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-23
7 | """
8 |
9 | def main():
10 | row = int(input('输入行数:'))
11 |
12 | # 初始化列表
13 | yh_triangle = [[] for _ in range(row)]
14 |
15 | for i in range(row):
16 | if i == 0:
17 | yh_triangle[i] = [1]
18 | elif i == 1:
19 | yh_triangle[i] = [1, 1]
20 | else:
21 | yh_triangle[i].append(1)
22 | for j in range(1, len(yh_triangle[i - 1])):
23 | yh_triangle[i].append(yh_triangle[i - 1][j] + yh_triangle[i - 1][j - 1])
24 | yh_triangle[i].append(1)
25 | print(yh_triangle[i], end="\n")
26 |
27 |
28 | if __name__ == '__main__':
29 | main()
--------------------------------------------------------------------------------
/day07/index.md:
--------------------------------------------------------------------------------
1 | # Day07 - 字符串和常用数据结构
2 |
3 | ## 字符串
4 |
5 | ### 切片
6 |
7 | ```Python
8 | str2 = 'abc123456'
9 | # 从字符串中取出指定位置的字符(下标运算)
10 | print(str2[2]) # c
11 | # 字符串切片(从指定的开始索引到指定的结束索引)
12 | print(str2[2:5]) # c12
13 | print(str2[2:]) # c123456
14 | print(str2[2::2]) # c246
15 | print(str2[::2]) # ac246
16 | print(str2[::-1]) # 654321cba
17 | print(str2[-3:-1]) # 45
18 | ```
19 |
20 | - `[x:y]`:从下标 `x` 往后取到下标为 `y - 1`(半开区间)
21 | - `[x:]`:从下标 `x` 开始取到末尾
22 | - `[x::y]`:从下标 `x` 开始每间隔 `y` 取一个元素,取出的元素下标为 `x, x + y, x + 2y ......`
23 | - `[::y]`:从首项开始每间隔 `y` 取一个元素,取出元素下标为 `0, y, 2y ......`
24 | - `[-x:-y]`:从倒数第 3 个元素取到倒数第 2 个元素(-1 半开区间,所以取不到倒数第一个)
25 |
26 | 学习资料:[廖雪峰 Python 切片](https://www.liaoxuefeng.com/wiki/897692888725344/923029651584288)
27 |
28 | ## 列表
29 |
30 | - 排序
31 | - `list = sorted(list)` 返回排序后的结果
32 | - `list.sort()` 直接在列表对象上排序
33 |
34 | ### 生成器
35 |
36 | #### 列表生成式
37 |
38 | [列表生成式](https://www.liaoxuefeng.com/wiki/897692888725344/923029657876192)
39 |
40 | #### yield
41 |
42 | 通过 `yield` 关键字将一个普通函数改造成生成器函数。
43 |
44 | ```python
45 | def fib(n):
46 | a, b = 0, 1
47 | for _ in range(n):
48 | a, b = b, a + b
49 | yield a
50 |
51 |
52 | def main():
53 | for val in fib(20):
54 | print(val)
55 |
56 |
57 | if __name__ == '__main__':
58 | main()
59 | ```
60 |
61 | ## 元组
62 |
63 | - 元素**无法修改**
64 | - 一个不变的对象比一个可变的对象更加容易维护
65 | - 一个不变对象自动就是线程安全的,可以省去同步化的开销
66 | - 一个不变的对象方便被共享访问
67 | - 在创建时间和占用空间上都优于列表
68 |
69 | ```python
70 | # 定义元组
71 | t = ('test', 'test1', 'test2')
72 |
73 | # 列表转元组
74 | t = tuple(l)
75 | ```
76 |
77 | ## 集合
78 |
79 | - 不允许有重复元素
80 | - 可以计算交集、并集、差集
81 |
82 | ```python
83 | set1 = {1, 2, 3}
84 | set2 = set(range(1, 10))
85 |
86 | # 添加元素
87 | set1.add(4)
88 | set2.update([11, 12])
89 |
90 | # 移除元素
91 | set1.discard(1) # 如果元素不存在不会报错
92 | set2.remove(11) # 如果元素不存在会报错
93 |
94 | # 元组转集合
95 | set3 = set((1, 2, 3, 4, 5))
96 |
97 | # 集合的交集、并集、差集、对称差运算
98 | print(set1 & set2) #交
99 | # print(set1.intersection(set2))
100 | print(set1 | set2) #并
101 | # print(set1.union(set2))
102 | print(set1 - set2) #差
103 | # print(set1.difference(set2))
104 | print(set1 ^ set2) #对称差
105 | # print(set1.symmetric_difference(set2))
106 | # 判断子集和超集
107 | print(set2 <= set1)
108 | # print(set2.issubset(set1))
109 | print(set3 <= set1)
110 | # print(set3.issubset(set1))
111 | print(set1 >= set2)
112 | # print(set1.issuperset(set2))
113 | print(set1 >= set3)
114 | # print(set1.issuperset(set3))
115 | ```
116 |
117 | ## 字典
118 |
119 | - 键值对
120 |
121 | ```python
122 | scores = {"Tom": 100, "Jan": 88, "Som": 60}
123 | # 更新与新增
124 | scores.update(Maria=100, Jack=90)
125 | # 获取
126 | scores.get("Tom", 80)
127 | # 删除
128 | print(scores.popitem())
129 | print(scores.pop("Tom", 20))
130 | # 清空
131 | scores.clear()
132 | ```
133 |
134 | ## 练习
135 |
136 | ### 练习1:在屏幕上显示跑马灯文字
137 |
138 | ```python
139 | """
140 | 在屏幕上显示跑马灯文字
141 | 打印一段文字,休眠,清理屏幕,打印……
142 |
143 | Version: 1.0.0
144 | Author: Jalan
145 | Date: 2019-05-23
146 | """
147 | import os
148 | import time
149 |
150 | def main():
151 | content = "今天是个好日子啊……"
152 | while True:
153 | os.system('clear')
154 | print(content)
155 |
156 | # 休眠
157 | time.sleep(0.2)
158 | # 制造跑马灯效果
159 | content = content[1:] + content[0]
160 |
161 | if __name__ == "__main__":
162 | main()
163 | ```
164 |
165 | 知识点:
166 |
167 | - `time.sleep()` 休眠
168 | - `os.system('clear')` 清屏
169 |
170 | ### 练习2:设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成
171 |
172 | ```python
173 | """
174 | 设计一个函数产生指定长度的验证码,验证码由大小写字母和数字构成
175 |
176 | Version: 1.0.0
177 | Author: Jalan
178 | Date: 2019-05-23
179 | """
180 | import random
181 |
182 | def generate_code(code_length=4):
183 | """
184 | 生成指定长度的验证码
185 |
186 | :param code_len: 验证码长度(默认 4 个字符)
187 |
188 | :return: 由大小写英文字母和数字构成的随机验证码
189 | """
190 | # 大写字母
191 | upper_list = [chr(x) for x in range(ord('A'), ord('A') + 26)]
192 | #print(upper_list)
193 | # 小写字母
194 | lower_list = [chr(x) for x in range(ord('a'), ord('a') + 26)]
195 | #print(lower_list)
196 | # 0-9 数字
197 | digit_list = [x for x in range(0, 10)]
198 | #print(digit_list)
199 | res_list = upper_list + lower_list + digit_list
200 | res_list_len = len(res_list)
201 | code = ''
202 | for _ in range(code_length):
203 | index = random.randint(0, res_list_len - 1)
204 | code += res_list[index]
205 | return code
206 |
207 | def main():
208 | code_len = int(input('请输入验证码长度:'))
209 | print(generate_code(code_len))
210 |
211 | if __name__ == '__main__':
212 | main()
213 | ```
214 |
215 | 因为懒得手打字母表,所以用了列表生成式用于生成 26 个字母。
216 |
217 | 知识点:
218 |
219 | - `ord()`:是 `chr()` 函数(对于8位的ASCII字符串)或 `unichr()` 函数(对于 Unicode 对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值
220 | - `chr()`:用一个范围在 `range(256)` 内的(就是0~255)整数作参数,返回一个对应的字符
221 |
222 | 参考:
223 |
224 | - [Python ord() 函数](https://www.runoob.com/python/python-func-ord.html)
225 | - [Python chr() 函数](https://www.runoob.com/python/python-func-chr.html)
226 |
227 | ### 练习3:设计一个函数返回给定文件名的后缀名
228 |
229 | ```python
230 | """
231 | 设计一个函数返回给定文件名的后缀名
232 |
233 | Version: 1.0.0
234 | Author: Jalan
235 | Date: 2019-05-23
236 | """
237 |
238 | def get_suffix(filename, has_dot=True):
239 | """
240 | 获取文件名后缀
241 |
242 | :param filename: 文件名
243 | :param has_dot: 后缀是否需要带点
244 | :return: 文件名后缀
245 | """
246 | pos = filename.rfind('.')
247 | if pos != -1:
248 | index = pos if has_dot else pos + 1
249 | return filename[index:]
250 | else:
251 | return ''
252 |
253 | def main():
254 | filename = str(input('输入文件名:'))
255 | print(get_suffix(filename, False))
256 |
257 | if __name__ == '__main__':
258 | main()
259 | ```
260 |
261 | 知识点:
262 |
263 | - [Python3 rfind()方法](https://www.runoob.com/python3/python3-string-rfind.html),返回字符串最后一次出现的位置
264 |
265 | ### 练习4:设计一个函数返回传入的列表中最大和第二大的元素的值
266 |
267 | ```python
268 | """
269 | 练习4:设计一个函数返回传入的列表中最大和第二大的元素的值
270 |
271 | Version: 1.0.0
272 | Author: Jalan
273 | Date: 2019-05-23
274 | """
275 |
276 | def get_top2_element(element_list):
277 | """
278 | 返回传入列表最大和第二大元素的值
279 |
280 | :param element_list: 传入列表
281 | :return 最大和第二大元素
282 | """
283 | element_list.sort(reverse=True)
284 | return element_list[:2]
285 |
286 | def main():
287 | element_list = [2, 5, 10, 22]
288 | print(get_top2_element(element_list))
289 |
290 | if __name__ == '__main__':
291 | main()
292 | ```
293 |
294 | 偷懒,直接用了 `sort`。看了下骆昊老师的例子是用了交换的方法,循环遍历列表,然后找到比当前 m1 m2 大的数就进行替换。
295 |
296 | ### 练习5:计算指定的年月日是这一年的第几天
297 |
298 | ```
299 | """
300 | 练习5:计算指定的年月日是这一年的第几天
301 |
302 | Version: 1.0.0
303 | Author: Jalan
304 | Date: 2019-05-23
305 | """
306 |
307 | def is_leap_year(year):
308 | """
309 | 判断是否是闰年
310 |
311 | :param year: 年
312 | :return 闰年返回 True,非闰年返回 False
313 | """
314 | return year % 4 == 0 and year % 100 != 0 or year % 400 == 0
315 |
316 | def which_day(year, month, day):
317 | """
318 | 返回指定的年月日是这一年的第几天
319 |
320 | :param year: 年
321 | :param month: 月
322 | :param day: 日
323 | :return 第几天
324 | """
325 | month_day = {
326 | 1: 31,
327 | 2: 28,
328 | 3: 31,
329 | 4: 30,
330 | 5: 31,
331 | 6: 30,
332 | 7: 31,
333 | 8: 31,
334 | 9: 30,
335 | 10: 31,
336 | 11: 30,
337 | 12: 31
338 | }
339 |
340 | # 闰年
341 | if is_leap_year:
342 | month_day[2] = 29
343 |
344 | day_count = 0
345 | for i in range(1, month):
346 | day_count += month_day[i]
347 | day_count += day
348 |
349 | return day_count
350 |
351 |
352 | def main():
353 | print(which_day(2019, 5, 23))
354 |
355 | if __name__ == '__main__':
356 | main()
357 | ```
358 |
359 | ### 练习6:打印杨辉三角
360 |
361 | ```python
362 | """
363 | 练习6:打印杨辉三角
364 |
365 | Version: 1.0.0
366 | Author: Jalan
367 | Date: 2019-05-23
368 | """
369 |
370 | def main():
371 | row = int(input('输入行数:'))
372 |
373 | # 初始化列表
374 | yh_triangle = [[] for _ in range(row)]
375 |
376 | for i in range(row):
377 | if i == 0:
378 | yh_triangle[i] = [1]
379 | elif i == 1:
380 | yh_triangle[i] = [1, 1]
381 | else:
382 | yh_triangle[i].append(1)
383 | for j in range(1, len(yh_triangle[i - 1])):
384 | # 每个数等于它上方两数之和
385 | yh_triangle[i].append(yh_triangle[i - 1][j] + yh_triangle[i - 1][j - 1])
386 | yh_triangle[i].append(1)
387 | print(yh_triangle[i], end="\n")
388 |
389 |
390 | if __name__ == '__main__':
391 | main()
392 | ```
393 |
394 | ## 综合案例
395 |
396 | ### 案例1:双色球选号
397 |
398 | 不想去了解双色球的规则了。。。这题先放空。。。
399 |
400 | ### 案例2:约瑟夫环问题
401 |
402 | [约瑟夫问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98)
403 |
404 | 用模拟整个过程的方式来做,被扔掉的人标记 `False`。
405 |
406 | ```python
407 | """
408 | 约瑟夫问题
409 |
410 | Version: 1.0.0
411 | Author: Jalan
412 | Date: 2019-05-23
413 | """
414 |
415 | def main():
416 | # 初始化,还没被扔掉的标为 True
417 | persons = [True for _ in range(30)]
418 | count, index, number = 0, 0, 0
419 | while count < 15:
420 | if persons[index]:
421 | number += 1 # 计数
422 | if number == 9:
423 | # 被扔掉
424 | persons[index] = False
425 | # 扔掉的人数 + 1
426 | count += 1
427 | # 重新开始计数
428 | number = 0
429 | index += 1
430 | index %= 30
431 |
432 | for person in persons:
433 | print('是基督徒' if person else '不是基督徒')
434 |
435 | if __name__ == "__main__":
436 | main()
437 | ```
438 |
439 | ### 案例3:井字棋游戏
440 |
441 | [井字棋](https://zh.wikipedia.org/wiki/%E4%BA%95%E5%AD%97%E6%A3%8B)。
442 |
443 | 顺便自己补充了判赢逻辑。
444 |
445 | ```
446 | """
447 | 井字棋
448 |
449 | Version: 1.0.0
450 | Author: Jalan
451 | Date: 2019-05-23
452 | """
453 |
454 | import os
455 |
456 | def print_board(board):
457 | """
458 | 画格子
459 |
460 | :param board: 每个格子的内容
461 | """
462 | print(board['TL'] + '|' + board['TM'] + '|' + board['TR'])
463 | print('-+-+-')
464 | print(board['ML'] + '|' + board['MM'] + '|' + board['MR'])
465 | print('-+-+-')
466 | print(board['BL'] + '|' + board['BM'] + '|' + board['BR'])
467 |
468 | def is_winner(board, turn):
469 | """
470 | 判断走棋者是否是赢家
471 |
472 | :param board: 当前棋盘数据
473 | :param turn: 走棋者
474 | :return 走棋者是赢家返回 True,否则返回 False
475 | """
476 | return ((board['TL'] == turn and board['TM'] == turn and board['TR'] == turn) or
477 | (board['ML'] == turn and board['MM'] == turn and board['MR'] == turn) or
478 | (board['BL'] == turn and board['BM'] == turn and board['BR'] == turn) or
479 | (board['TL'] == turn and board['ML'] == turn and board['BL'] == turn) or
480 | (board['TM'] == turn and board['MM'] == turn and board['BM'] == turn) or
481 | (board['TR'] == turn and board['MR'] == turn and board['BR'] == turn) or
482 | (board['TL'] == turn and board['MM'] == turn and board['BR'] == turn) or
483 | (board['BL'] == turn and board['MM'] == turn and board['TR'] == turn))
484 |
485 | def main():
486 | # 初始化一个空棋盘
487 | init_board = {
488 | 'TL': ' ', 'TM': ' ', 'TR': ' ',
489 | 'ML': ' ', 'MM': ' ', 'MR': ' ',
490 | 'BL': ' ', 'BM': ' ', 'BR': ' '
491 | }
492 | # print_board(init_board)
493 |
494 | begin = True
495 |
496 | while begin:
497 | # 开始一盘新棋局
498 | current_board = init_board.copy()
499 | begin = False
500 |
501 | # 轮到 x 走
502 | turn = 'x'
503 | # 已经走了几个格子
504 | counter = 0
505 |
506 | # 清屏
507 | os.system('clear')
508 |
509 | print_board(current_board)
510 |
511 | while counter < 9:
512 | move = input('轮到 %s 走,请输入位置:' % turn)
513 | if current_board[move] == ' ':
514 | counter += 1
515 | current_board[move] = turn
516 |
517 | if is_winner(current_board, turn):
518 | print("产生赢家:%s 赢得胜利" % turn)
519 | break
520 |
521 | turn = 'o' if turn == 'x' else 'x'
522 |
523 | os.system('clear')
524 | print_board(current_board)
525 |
526 | choice = input('是否再玩一局?(y/n)')
527 | begin = choice == 'y'
528 |
529 |
530 | if __name__ == "__main__":
531 | main()
532 | ```
--------------------------------------------------------------------------------
/day08/code/practice1.py:
--------------------------------------------------------------------------------
1 | """
2 | 定义一个类描述数字时钟
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-24
7 | """
8 |
9 | class Clock:
10 | def __init__(self, hour=0, minute=0, second=0):
11 | """
12 | 初始化方法
13 |
14 | :param hour: 小时
15 | :param minute: 分钟
16 | :param second: 秒
17 | """
18 | self._hour = hour
19 | self._minute = minute
20 | self._second = second
21 |
22 | def show_time(self):
23 | """
24 | 显示时间
25 | """
26 | return "%02d:%02d:%02d" % (self._hour, self._minute, self._second)
27 |
28 | def run(self):
29 | """
30 | 走字
31 | """
32 | self._second += 1
33 | if self._second == 60:
34 | self._second = 0
35 | self._minute += 1
36 | if self._minute == 60:
37 | self._minute = 0
38 | self._hour += 1
39 | if self._hour == 24:
40 | self._hour = 0
41 |
42 | def main():
43 | # 12:01
44 | clock = Clock(0, 1, 0)
45 | while True:
46 | # 显示时间
47 | print(clock.show_time())
48 | # 走字
49 | clock.run()
50 |
51 | if __name__ == "__main__":
52 | main()
--------------------------------------------------------------------------------
/day08/code/practice2.py:
--------------------------------------------------------------------------------
1 | """
2 | 定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-25
7 | """
8 |
9 | import math
10 |
11 | class Point:
12 | def __init__(self, x=0, y=0):
13 | """
14 | 初始化点
15 |
16 | :param x: 坐标 x
17 | :param y: 坐标 y
18 | """
19 | self._x = x
20 | self._y = y
21 |
22 | def move_to(self, to_x=0, to_y=0):
23 | """
24 | 移动点
25 |
26 | :param to_x: 要移动到的 x 坐标
27 | :param to_y: 要移动到的 y 坐标
28 | """
29 | self._x = to_x
30 | self._y = to_y
31 |
32 | def distance(self, to_x=0, to_y=0):
33 | """
34 | 计算亮点距离
35 |
36 | :param to_x: 另一个点的坐标 x
37 | :param to_y: 另一个点的坐标 y
38 | """
39 | return math.sqrt((to_x - self._x)**2 + (to_y - self._y)**2)
40 |
41 | def __str__(self):
42 | """
43 | 魔法方法,当 print 对象时就会输出该方法中 return 的数据
44 | """
45 | return '(%s, %s)' % (str(self._x), str(self._y))
46 |
47 | def main():
48 | point = Point(1, 2)
49 | point.move_to(4, 5)
50 | print(point.distance(4, 6))
51 | print(point)
52 |
53 | if __name__ == "__main__":
54 | main()
--------------------------------------------------------------------------------
/day08/index.md:
--------------------------------------------------------------------------------
1 | # Day 08 - 面向对象编程基础
2 |
3 | > We are all consenting adults here.
4 |
5 | - 双下划线的变量或方法表示私有
6 | - 但仍然可以被访问
7 | - 单下划线的变量表示属性受保护,本类以外的代码在访问这样的属性时应该要保持慎重
8 | - 面向对象的三大支柱
9 | - 封装:隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口
10 | - 继承
11 | - 多态
12 |
13 | ## 练习
14 |
15 | ### 练习1:定义一个类描述数字时钟
16 |
17 | ```python
18 | """
19 | 定义一个类描述数字时钟
20 |
21 | Version: 1.0.0
22 | Author: Jalan
23 | Date: 2019-05-24
24 | """
25 |
26 | class Clock:
27 | def __init__(self, hour=0, minute=0, second=0):
28 | """
29 | 初始化方法
30 |
31 | :param hour: 小时
32 | :param minute: 分钟
33 | :param second: 秒
34 | """
35 | self._hour = hour
36 | self._minute = minute
37 | self._second = second
38 |
39 | def show_time(self):
40 | """
41 | 显示时间
42 | """
43 | return "%02d:%02d:%02d" % (self._hour, self._minute, self._second)
44 |
45 | def run(self):
46 | """
47 | 走字
48 | """
49 | self._second += 1
50 | if self._second == 60:
51 | self._second = 0
52 | self._minute += 1
53 | if self._minute == 60:
54 | self._minute = 0
55 | self._hour += 1
56 | if self._hour == 24:
57 | self._hour = 0
58 |
59 | def main():
60 | # 12:01
61 | clock = Clock(0, 1, 0)
62 | while True:
63 | # 显示时间
64 | print(clock.show_time())
65 | # 走字
66 | clock.run()
67 |
68 | if __name__ == "__main__":
69 | main()
70 | ```
71 |
72 | ### 练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
73 |
74 | ```python
75 | """
76 | 定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
77 |
78 | Version: 1.0.0
79 | Author: Jalan
80 | Date: 2019-05-25
81 | """
82 |
83 | import math
84 |
85 | class Point:
86 | def __init__(self, x=0, y=0):
87 | """
88 | 初始化点
89 |
90 | :param x: 坐标 x
91 | :param y: 坐标 y
92 | """
93 | self._x = x
94 | self._y = y
95 |
96 | def move_to(self, to_x=0, to_y=0):
97 | """
98 | 移动点
99 |
100 | :param to_x: 要移动到的 x 坐标
101 | :param to_y: 要移动到的 y 坐标
102 | """
103 | self._x = to_x
104 | self._y = to_y
105 |
106 | def distance(self, to_x=0, to_y=0):
107 | """
108 | 计算亮点距离
109 |
110 | :param to_x: 另一个点的坐标 x
111 | :param to_y: 另一个点的坐标 y
112 | """
113 | return math.sqrt((to_x - self._x)**2 + (to_y - self._y)**2)
114 |
115 | def __str__(self):
116 | """
117 | 魔法方法,当 print 对象时就会输出该方法中 return 的数据
118 | """
119 | return '(%s, %s)' % (str(self._x), str(self._y))
120 |
121 | def main():
122 | point = Point(1, 2)
123 | point.move_to(4, 5)
124 | print(point.distance(4, 6))
125 | print(point)
126 |
127 | if __name__ == "__main__":
128 | main()
129 | ```
130 |
131 | 知识点:
132 |
133 | - `__str__()` 魔法方法:[Python __str__() 方法](https://www.runoob.com/note/41154)
134 |
135 | ----
136 |
137 | 说一说开头的那句 We are all consenting adults here。
138 |
139 | 学习时搜索资料的适合在 [知乎](https://www.zhihu.com/question/20030486) 看到:
140 |
141 | > Nothing is really private in python. No class or class instance cankeep you away from all what's inside (this makes introspectionpossible and powerful). Python trusts you. It says "hey, if you wantto go poking around in dark places, I'm gonna trust that you've gota good reason and you're not making trouble."After all, we're all consenting adults here.
142 | > Python中没有东西是真正private的. 任何类和对象都不会阻止你窥探他们的内部,这使得Python的自省异常强大. Python 对你的态度是信任的,它说:“hey,如果你想尝试使用黑魔法,那么放心大胆的去吧,我相信你一定是有自己的理由的,知道自己在干嘛,并且不会捅出篓子,懂得点到为止”话说回来,大家毕竟都是成年人了,懂得为自己的行为负责,都知道自己在干嘛,所以你想干什么我不会拦着你。
143 |
144 | 看完好感动。编程语言对我们这么信任,那么一定要好好写代码作为回报呀!
145 |
146 | Powered By Love~ ❤️
147 |
148 | ## 其他资料
149 |
150 | - [python定义类()中写object和不写的区别](https://www.cnblogs.com/wujingqiao/p/9668583.html)
151 | - [Python class inherits object](https://stackoverflow.com/questions/4015417/python-class-inherits-object)
152 |
153 |
--------------------------------------------------------------------------------
/day09/code/case1.py:
--------------------------------------------------------------------------------
1 | """
2 | 奥特曼打小怪兽
3 |
4 | Version: 1.0.0
5 | Author: Jalan
6 | Date: 2019-05-25
7 | """
8 |
9 | from abc import ABCMeta, abstractclassmethod
10 | from random import randint, randrange
11 | import time
12 |
13 | class Fighter(metaclass=ABCMeta):
14 | """
15 | 攻击者
16 | """
17 |
18 | __slots__ = ('_name', '_hp')
19 |
20 | def __init__(self, name, hp):
21 | """
22 | 初始化攻击者
23 |
24 | :param name: 攻击者姓名
25 | :param hp: 攻击者 hp
26 | """
27 | self._name = name
28 | self._hp = hp
29 |
30 | @property
31 | def name(self):
32 | return self._name
33 |
34 | @property
35 | def hp(self):
36 | return self._hp
37 |
38 | @hp.setter
39 | def hp(self, hp):
40 | self._hp = hp if hp > 0 else 0
41 |
42 | def is_alive(self):
43 | """
44 | 判断是否存活
45 |
46 | :return 如果存活返回 True,否则返回 False
47 | """
48 | return True if self._hp > 0 else False
49 |
50 | @abstractclassmethod
51 | def attack(self, other):
52 | """
53 | 普通攻击
54 |
55 | :param other: 攻击对象
56 | """
57 | pass
58 |
59 | class Ultraman(Fighter):
60 | """
61 | 奥特曼
62 | """
63 |
64 | __slots__ = ('_name', '_hp', '_mp')
65 |
66 | def __init__(self, name, hp):
67 | """
68 | 初始化奥特曼
69 |
70 | :param name: 奥特曼名字
71 | :param hp: 奥特曼 hp
72 | :param mp: 奥特曼魔法蓄力值
73 | """
74 | super().__init__(name, hp)
75 | self._mp = 100
76 |
77 | def attack(self, other):
78 | """
79 | 普通攻击一拳 -10
80 | """
81 | num = randint(1, 10)
82 | if num == 1:
83 | self._magic_attack(other)
84 | else:
85 | other.hp -= 10
86 |
87 |
88 | def _magic_attack(self, other):
89 | """
90 | 魔法攻击
91 |
92 | :param other: 攻击对象
93 | """
94 | if self._mp == 100:
95 | other.hp -= 50
96 | return True
97 | else:
98 | return False
99 |
100 | def resume_mp(self):
101 | """
102 | 恢复 mp
103 | """
104 | if self._mp < 100:
105 | self._mp += 10
106 |
107 | def __str__(self):
108 | return '奥特曼 %s 生命值 %s' % (self._name, self._hp)
109 |
110 | class OnePunchMan(Fighter):
111 | """
112 | 琦玉老师
113 | """
114 |
115 | __slots__ = ('_name', '_hp')
116 |
117 | def __init__(self, name):
118 | """
119 | 初始化一个一拳超人
120 | """
121 | self._name = name
122 | self._hp = float('inf')
123 |
124 | def attack(self, other):
125 | """
126 | 一拳打死
127 |
128 | :param other: 攻击对象
129 | """
130 | other._hp = 0
131 |
132 | def __str__(self):
133 | return '琦玉老师出场'
134 |
135 | class Monster(Fighter):
136 | """
137 | 小怪兽
138 | """
139 |
140 | __slots__ = ('_name', '_hp', '_hurt')
141 |
142 | def __init__(self, name, hp):
143 | """
144 | 初始化小怪兽
145 | """
146 | self._name = name
147 | self._hp = hp
148 |
149 |
150 | def attack(self, other):
151 | """
152 | 普通攻击
153 | """
154 | other.hp -= 5
155 |
156 | def __str__(self):
157 | return '小怪兽 %s 生命值 %s' % (self._name, self._hp)
158 |
159 |
160 | def is_any_alive(monsters):
161 | """
162 | 是否还有小怪兽存活
163 |
164 | :return 是返回 True,否返回 False
165 | """
166 | for monster in monsters:
167 | if monster.is_alive:
168 | return True
169 | return False
170 |
171 | def select_monster(monsters):
172 | """
173 | 选择一只小怪兽
174 |
175 | :return 返回小怪兽
176 | """
177 | monsters_len = len(monsters)
178 | while True:
179 | index = randrange(monsters_len)
180 | monster = monsters[index]
181 | if monster.is_alive:
182 | return monster
183 |
184 | def main():
185 | u = Ultraman('迪迦', 500)
186 | m1 = Monster('小龙虾', 100)
187 | m2 = Monster('大螃蟹', 120)
188 | m3 = Monster('老乌龟', 200)
189 | monsters = [m1, m2, m3]
190 | one = OnePunchMan('琦玉老师')
191 |
192 | while u.is_alive and is_any_alive(monsters):
193 | target = select_monster(monsters)
194 | # 小怪兽被打
195 | u.attack(target)
196 |
197 | # 小怪兽打奥特曼
198 | for monster in monsters:
199 | if monster.is_alive:
200 | monster.attack(u)
201 |
202 | # 判断是否可以召唤琦玉老师
203 | one_punc_num = randint(1, 100)
204 | if one_punc_num == 1 and is_any_alive(monsters):
205 | target = select_monster(monsters)
206 | one.attack(target)
207 | print(one)
208 |
209 | print(target)
210 | print(u)
211 |
212 | time.sleep(2)
213 |
214 | if __name__ == "__main__":
215 | main()
--------------------------------------------------------------------------------
/day09/code/case2.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/day09/code/case2.py
--------------------------------------------------------------------------------
/day09/code/case3.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/day09/code/case3.py
--------------------------------------------------------------------------------
/day09/index.md:
--------------------------------------------------------------------------------
1 | # Day09 - 面向对象进阶
2 |
3 | ## @property 装饰器
4 |
5 | - 防止私有变量在外部被随意访问和修改,避免写复杂的 setter 和 getter 方法
6 | - 负责把一个方法变成属性调用
7 | - 关键字
8 | - `@property`
9 | - `@name.setter`
10 |
11 | ```python
12 | class Person:
13 |
14 | def __init__(self, name, age):
15 | self._name = name
16 | self._age = age
17 |
18 | @property
19 | def name(self):
20 | return self._name
21 |
22 | @name.setter
23 | def name(self, age):
24 | self._age = age
25 |
26 | def main():
27 | person = Person('Jalan', 18)
28 | person.name = 'Jay'
29 | ```
30 |
31 | 参考:[使用@property](https://www.liaoxuefeng.com/wiki/897692888725344/923030547069856)
32 |
33 | ## __slots__ 魔法
34 |
35 | - 限定自定义类型的对象只能绑定某些属性
36 | - 只对当前类的对象生效,对子类并不起任何作用
37 |
38 | ```python
39 | class Person:
40 | # Person 类只能绑定 _name 和 _age 属性
41 | __slots__ = ('_name', '_age')
42 | ```
43 |
44 | ## 静态方法和类方法
45 |
46 | ### 静态方法
47 |
48 | 众所周知,静态方法属于类而不属于对象。在之前的编程过程中,如果调用一个方法时不想 new 一个对象出来,我就会把它定义成静态方法(粗暴),但始终不知道要定义静态方法的真正时机是什么。
49 |
50 | 骆昊老师的教程里举了个例子,算是看明白了:
51 |
52 | > 我们写在类中的方法并不需要都是对象方法,例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。
53 |
54 | 定义静态方法关键字:`@staticmethod`
55 |
56 | ### 类方法
57 |
58 | - `@classmethod`
59 | - `cls` 表示类本身
60 | - 通过 `cls` 可以获取和类相关的信息并且可以创建出类的对象
61 |
62 | ```python
63 | class Clock:
64 |
65 | def __init__(self, hour=0, minute=0, second=0):
66 | self._hour = hour
67 | self._minute = minute
68 | self._second = second
69 |
70 | @classmethod
71 | def now(cls):
72 | # 返回一个类对象
73 | return cls(1, 2, 3)
74 | ```
75 |
76 | ## 类之间的关系
77 |
78 | - is-a:继承或泛化
79 | - has-a:关联。例如部门和员工的关系
80 | - use-a:依赖。例如方法中使用到某个其他对象
81 |
82 | ## 继承和多态
83 |
84 | - 子类比父类拥有更多的功能。用子类对象替换一个父类对象,[里氏替换原则](https://zh.wikipedia.org/wiki/%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99)
85 | - 继承的写法:`class Teacher(Person)`,和其他编程语言不同,没有什么 `extends` 关键字,而是直接在类后的括号里标明所要继承的父类
86 | - 子类对父类已有方法给出新的实现版本:重写(override)。当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)
87 | - 顺便复习:重载是指相同函数名的不同使用方式,Python 中没有重载
88 |
89 | ### 抽象类
90 |
91 | - Python 在语法层面没有像 Java 或 C# 那样提供对抽象类的支持
92 | - 但可以通过 abc 模块的 ABCMeta 元类和 abstractmethod 包装器来达到抽象类的效果
93 | - 如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)
94 |
95 | ```python
96 | from abc import ABCMeta, abstractmethod
97 |
98 |
99 | class Pet(object, metaclass=ABCMeta):
100 | """宠物"""
101 |
102 | def __init__(self, nickname):
103 | self._nickname = nickname
104 |
105 | @abstractmethod
106 | def make_voice(self):
107 | """发出声音"""
108 | pass
109 |
110 |
111 | class Dog(Pet):
112 | """狗"""
113 |
114 | def make_voice(self):
115 | print('%s: 汪汪汪...' % self._nickname)
116 |
117 |
118 | class Cat(Pet):
119 | """猫"""
120 |
121 | def make_voice(self):
122 | print('%s: 喵...喵...' % self._nickname)
123 |
124 |
125 | def main():
126 | pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
127 | for pet in pets:
128 | # make_voice 表现出了多态行为
129 | pet.make_voice()
130 |
131 |
132 | if __name__ == '__main__':
133 | main()
134 | ```
135 |
136 | ## 综合案例
137 |
138 | ### 案例1:奥特曼打小怪兽
139 |
140 | 大概看了一下代码,描述一下这个案例。
141 |
142 | 首先需要定义一个攻击者类 `Fighter`,奥特曼和小怪兽都是攻击者。攻击者的基本属性有姓名 `name` 和生命值 `hp`。
143 |
144 | - 奥特曼:
145 | - 90% 概率使用普通攻击。普通攻击打一拳 hp-10
146 | - 10% 概率使用魔法攻击,但魔法攻击需要蓄力,蓄力值达到 100 才可以发动。每回合可以恢复蓄力值 10 点。魔法攻击打一拳 hp-50
147 | - 小怪兽:
148 | - 只会普通攻击,每一回合结束奥特曼会被所有小怪兽打一拳,打一拳 hp-5
149 | - 琦玉老师:
150 | - 每回合除奥特曼出击外有 1% 的概率召唤琦玉老师,一拳解决一只小怪兽
151 |
152 | ```python
153 | """
154 | 奥特曼打小怪兽
155 |
156 | Version: 1.0.0
157 | Author: Jalan
158 | Date: 2019-05-25
159 | """
160 |
161 | from abc import ABCMeta, abstractclassmethod
162 | from random import randint, randrange
163 | import time
164 |
165 | class Fighter(metaclass=ABCMeta):
166 | """
167 | 攻击者
168 | """
169 |
170 | __slots__ = ('_name', '_hp')
171 |
172 | def __init__(self, name, hp):
173 | """
174 | 初始化攻击者
175 |
176 | :param name: 攻击者姓名
177 | :param hp: 攻击者 hp
178 | """
179 | self._name = name
180 | self._hp = hp
181 |
182 | @property
183 | def name(self):
184 | return self._name
185 |
186 | @property
187 | def hp(self):
188 | return self._hp
189 |
190 | @hp.setter
191 | def hp(self, hp):
192 | self._hp = hp if hp > 0 else 0
193 |
194 | def is_alive(self):
195 | """
196 | 判断是否存活
197 |
198 | :return 如果存活返回 True,否则返回 False
199 | """
200 | return True if self._hp > 0 else False
201 |
202 | @abstractclassmethod
203 | def attack(self, other):
204 | """
205 | 普通攻击
206 |
207 | :param other: 攻击对象
208 | """
209 | pass
210 |
211 | class Ultraman(Fighter):
212 | """
213 | 奥特曼
214 | """
215 |
216 | __slots__ = ('_name', '_hp', '_mp')
217 |
218 | def __init__(self, name, hp):
219 | """
220 | 初始化奥特曼
221 |
222 | :param name: 奥特曼名字
223 | :param hp: 奥特曼 hp
224 | :param mp: 奥特曼魔法蓄力值
225 | """
226 | super().__init__(name, hp)
227 | self._mp = 100
228 |
229 | def attack(self, other):
230 | """
231 | 普通攻击一拳 -10
232 | """
233 | num = randint(1, 10)
234 | if num == 1:
235 | self._magic_attack(other)
236 | else:
237 | other.hp -= 10
238 |
239 |
240 | def _magic_attack(self, other):
241 | """
242 | 魔法攻击
243 |
244 | :param other: 攻击对象
245 | """
246 | if self._mp == 100:
247 | other.hp -= 50
248 | return True
249 | else:
250 | return False
251 |
252 | def resume_mp(self):
253 | """
254 | 恢复 mp
255 | """
256 | if self._mp < 100:
257 | self._mp += 10
258 |
259 | def __str__(self):
260 | return '奥特曼 %s 生命值 %s' % (self._name, self._hp)
261 |
262 | class OnePunchMan(Fighter):
263 | """
264 | 琦玉老师
265 | """
266 |
267 | __slots__ = ('_name', '_hp')
268 |
269 | def __init__(self, name):
270 | """
271 | 初始化一个一拳超人
272 | """
273 | self._name = name
274 | self._hp = float('inf')
275 |
276 | def attack(self, other):
277 | """
278 | 一拳打死
279 |
280 | :param other: 攻击对象
281 | """
282 | other._hp = 0
283 |
284 | def __str__(self):
285 | return '琦玉老师出场'
286 |
287 | class Monster(Fighter):
288 | """
289 | 小怪兽
290 | """
291 |
292 | __slots__ = ('_name', '_hp', '_hurt')
293 |
294 | def __init__(self, name, hp):
295 | """
296 | 初始化小怪兽
297 | """
298 | self._name = name
299 | self._hp = hp
300 |
301 |
302 | def attack(self, other):
303 | """
304 | 普通攻击
305 | """
306 | other.hp -= 5
307 |
308 | def __str__(self):
309 | return '小怪兽 %s 生命值 %s' % (self._name, self._hp)
310 |
311 |
312 | def is_any_alive(monsters):
313 | """
314 | 是否还有小怪兽存活
315 |
316 | :return 是返回 True,否返回 False
317 | """
318 | for monster in monsters:
319 | if monster.is_alive:
320 | return True
321 | return False
322 |
323 | def select_monster(monsters):
324 | """
325 | 选择一只小怪兽
326 |
327 | :return 返回小怪兽
328 | """
329 | monsters_len = len(monsters)
330 | while True:
331 | index = randrange(monsters_len)
332 | monster = monsters[index]
333 | if monster.is_alive:
334 | return monster
335 |
336 | def main():
337 | u = Ultraman('迪迦', 500)
338 | m1 = Monster('小龙虾', 100)
339 | m2 = Monster('大螃蟹', 120)
340 | m3 = Monster('老乌龟', 200)
341 | monsters = [m1, m2, m3]
342 | one = OnePunchMan('琦玉老师')
343 |
344 | while u.is_alive and is_any_alive(monsters):
345 | target = select_monster(monsters)
346 | # 小怪兽被打
347 | u.attack(target)
348 |
349 | # 小怪兽打奥特曼
350 | for monster in monsters:
351 | if monster.is_alive:
352 | monster.attack(u)
353 |
354 | # 判断是否可以召唤琦玉老师
355 | one_punc_num = randint(1, 100)
356 | if one_punc_num == 1 and is_any_alive(monsters):
357 | target = select_monster(monsters)
358 | one.attack(target)
359 | print(one)
360 |
361 | print(target)
362 | print(u)
363 |
364 | time.sleep(2)
365 |
366 | if __name__ == "__main__":
367 | main()
368 | ```
--------------------------------------------------------------------------------
/day11/index.md:
--------------------------------------------------------------------------------
1 | # Day11 - 文件和异常
2 |
3 | ## 读写文本
4 |
5 | `open()` 函数:
6 |
7 | - 文件名
8 | - 操作模式
9 | - 编码(如果不能保证保存文件时使用的编码方式与encoding参数指定的编码方式是一致的,那么就可能因无法解码字符而导致读取失败)
10 |
11 | | 操作模式 | 具体含义 |
12 | | -------- | -------------------------------- |
13 | | `'r'` | 读取 (默认) |
14 | | `'w'` | 写入(会先截断之前的内容) |
15 | | `'x'` | 写入,如果文件已经存在会产生异常 |
16 | | `'a'` | 追加,将内容写入到已有文件的末尾 |
17 | | `'b'` | 二进制模式 |
18 | | `'t'` | 文本模式(默认) |
19 | | `'+'` | 更新(既可以读又可以写) |
20 |
21 | 如何根据应用程序的需要来设置操作模式:
22 |
23 | 
24 |
25 | ### 方法
26 |
27 | - `f.read()` 读取所有
28 | - `f.readlines()` 按行读取
29 | - `for line in f`
30 |
31 | ### 读写 JSON
32 |
33 | Python 的 json 模块。
34 |
35 | - `dump` - 将 Python 对象按照 JSON 格式序列化到文件中
36 | - `dumps` - 将 Python 对象处理成 JSON 格式的字符串
37 | - `load` - 将文件中的 JSON 数据反序列化成对象
38 | - `loads` - 将字符串的内容反序列化成 Python 对象
39 |
40 | ## 异常机制
41 |
42 | ```python
43 | try:
44 | pass
45 | except FileNotFoundError:
46 | pass
47 | except LookupError:
48 | pass
49 | except UnicodeDecodeError:
50 | pass
51 | finally:
52 | # 无论是否有异常最终都会执行
53 | ```
54 |
55 | ## 其他
56 |
57 | - 使用 `with` 关键字指定文件对象上下文环境,在离开上下文环境时会自动释放文件资源
58 | - 也可以在 `finally` 中进行 `f.close()`
59 |
60 | ## 推荐阅读
61 |
62 | - [总结:Python中的异常处理](https://segmentfault.com/a/1190000007736783)
--------------------------------------------------------------------------------
/day12/index.md:
--------------------------------------------------------------------------------
1 | # Day12 - 使用正则表达式
2 |
3 | - 用于描述字符串规则的工具
4 | - 定义了字符串的匹配模式
5 |
6 | ## Python 对正则的支持
7 |
8 | 使用 `re` 模块来支持正则表达式相关操作,核心函数:
9 |
10 | | 函数 | 说明 |
11 | | -------------------------------------------- | ------------------------------------------------------------ |
12 | | compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 |
13 | | match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None |
14 | | search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None |
15 | | split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 |
16 | | sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count指定替换的次数 |
17 | | fullmatch(pattern, string, flags=0) | match 函数的完全匹配(从字符串开头到结尾)版本 |
18 | | findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 |
19 | | finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 |
20 | | purge() | 清除隐式编译的正则表达式的缓存 |
21 | | re.I / re.IGNORECASE | 忽略大小写匹配标记 |
22 | | re.M / re.MULTILINE | 多行匹配标记 |
23 |
24 | ## 推荐阅读
25 |
26 | - [正则表达式30分钟入门教程](https://deerchao.net/tutorials/regex/regex.htm)
27 | - [正则表达式不要背](https://juejin.im/post/5cdcd42551882568651554e6)
--------------------------------------------------------------------------------
/day13/index.md:
--------------------------------------------------------------------------------
1 | # Day13 - 进程和线程
2 |
3 | ## 概念
4 |
5 | - 进程分配资源的基本单位
6 | - 一个进程可以包含多个线程
7 | - 线程是调度的基本单位
8 |
9 | ## 关于fork
10 |
11 | - 用来创建进程
12 | - 调用 `fork()` 的是父进程
13 | - 创建出来的是子进程
14 | - 子进程是父进程的一个拷贝,但有自己的 PID
15 | - `fork()` 会返回两次
16 | - 父进程通过 `fork()` 返回值获取子进程 PID
17 | - 子进程中的返回值永远是 0
18 |
19 | ## Python 中的多进程
20 |
21 | ### 创建进程
22 |
23 | - os 模块提供了 `fork()` 函数
24 | - multiprocessing 模块中的 `Process` 类可以用来创建子进程:启动进程 `start` 方法;等待进程执行结束:`join` 方法
25 | - 批量启动进程的进程池 `Pool`
26 | - 进程间通信队列 `Queue`
27 | - 管道 `Pipe`
28 |
29 | ### 进程间通信
30 |
31 | - 使用 multiprocessing 模块中的 `Queue`(底层通过管道和信号量实现)
32 |
33 | ## Python 中的多线程
34 |
35 | - threading 模块
36 | - 使用 `Tread` 类创建线程
37 | - 也可以继承 `Thread` 创建自己的线程类
38 |
39 | ```python
40 | from threading import Thread
41 | ```
42 |
43 | - Python 多线程并不能发挥 CPU 的多核特性
44 |
45 | ### 线程间通信
46 |
47 | - 线程共享进程的内存空间
48 | - 实现
49 | - 设置全局变量用于共享
50 | - 注意“临界资源”的处理问题:加锁,只有获得缩的线程才能访问临界资源
51 |
52 | ```python
53 | from threading import Lock
54 |
55 | lock = Lock()
56 | # 获取锁
57 | lock.acquire()
58 | # 释放锁
59 | lock.release()
60 | ```
61 |
62 | ## 多进程还是多线程
63 |
64 | - 无论是多线程还是多进程,数量过多都会导致效率下降
65 | - 操作系统切换线程和进程时需要:
66 | - 保存现场环境(CPU寄存器状态、内存页等)
67 | - 新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等)
68 |
69 | ## 单进程 + 异步 I/O
70 |
71 | - 充分利用操作系统提供的异步 I/O 支持,可以使用单进程单线程执行多任务
72 | - 且看 Nginx
73 | - 单核 CPU 上采用单进程模型可以有效支持多任务
74 | - 在多核 CPU 上可以运行多个进程(数量与 CPU 核心数相同)
75 | - 单线程 + 异步 I/O 在 Python 中称为协程
76 | - 极高的执行效率
77 | - 子程序切换不是线程切换,而是由程序自身控制,因此没有线程切换的开销
78 | - 不需要多线程的锁机制。因为只有一个线程
79 |
80 | ## 案例
--------------------------------------------------------------------------------
/day14-a/index.md:
--------------------------------------------------------------------------------
1 | # Day14A - 网络编程入门
2 |
3 | ## 计算机网络
4 |
5 | - 网络协议三大要素:语法、语义、时序
6 | - TCP/IP 四层模型,自底向上分别是:
7 | - 网络接口层
8 | - 网络层:IP 协议服务于该层,用于寻址和路由
9 | - 传输层
10 | - 应用层
11 | - 路由功能:存储转发我们发送到网络上的数据分组,让从源头发出的数据最终能够找到传送到目的地同路
12 | - TCP 的可靠性:
13 | 1. 数据不传丢不传错(利用握手、校验和重传机制可以实现)
14 | 2. 流量控制(通过滑动窗口匹配数据发送者和接收者之间的传输速度)
15 | 3. 拥塞控制(通过RTT时间以及对滑动窗口的控制缓解网络拥堵)
16 |
17 | ## 基于传输层协议的套接字编程
18 |
19 | 套接字就是一套用C语言写成的应用程序开发库,主要用于实现进程间通信和网络编程,在网络应用开发中被广泛使用。
20 |
21 | ### TCP 套接字
22 |
23 | TCP 套接字就是使用 TCP 协议提供的传输服务来实现网络通信的编程接口。
24 |
25 | 在 Python 中:
26 |
27 | - 创建 `socket` 对象
28 | - 指定 `type` 属性为 `SOCK_STREAM`
29 |
30 | #### 实现服务器程序
31 |
32 | ```python
33 | from socket import socket, SOCK_STREAM, AF_INET
34 | from datetime import datetime
35 |
36 |
37 | def main():
38 | # 1.创建套接字对象并指定使用哪种传输服务
39 | # family=AF_INET - IPv4地址
40 | # family=AF_INET6 - IPv6地址
41 | # type=SOCK_STREAM - TCP套接字
42 | # type=SOCK_DGRAM - UDP套接字
43 | # type=SOCK_RAW - 原始套接字
44 | server = socket(family=AF_INET, type=SOCK_STREAM)
45 | # 2.绑定IP地址和端口(端口用于区分不同的服务)
46 | # 同一时间在同一个端口上只能绑定一个服务否则报错
47 | server.bind(('192.168.1.2', 6789))
48 | # 3.开启监听 - 监听客户端连接到服务器
49 | # 参数512可以理解为连接队列的大小
50 | server.listen(512)
51 | print('服务器启动开始监听...')
52 | while True:
53 | # 4.通过循环接收客户端的连接并作出相应的处理(提供服务)
54 | # accept方法是一个阻塞方法如果没有客户端连接到服务器代码不会向下执行
55 | # accept方法返回一个元组其中的第一个元素是客户端对象
56 | # 第二个元素是连接到服务器的客户端的地址(由IP和端口两部分构成)
57 | client, addr = server.accept()
58 | print(str(addr) + '连接到了服务器.')
59 | # 5.发送数据
60 | client.send(str(datetime.now()).encode('utf-8'))
61 | # 6.断开连接
62 | client.close()
63 |
64 |
65 | if __name__ == '__main__':
66 | main()
67 | ```
68 |
69 | 运行时:
70 |
71 | ```
72 | telnet 192.168.1.2 6789
73 | ```
74 |
75 | #### 实现客户端程序
76 |
77 | ```python
78 | from socket import socket
79 |
80 |
81 | def main():
82 | # 1.创建套接字对象默认使用IPv4和TCP协议
83 | client = socket()
84 | # 2.连接到服务器(需要指定IP地址和端口)
85 | client.connect(('192.168.1.2', 6789))
86 | # 3.从服务器接收数据
87 | print(client.recv(1024).decode('utf-8'))
88 | client.close()
89 |
90 |
91 | if __name__ == '__main__':
92 | main()
93 | ```
94 |
95 | ### UDP 套接字
96 |
97 | 与 TCP 的区别:
98 |
99 | - UDP 不对传输的可靠性和可达性做保证
100 | - 避免了 TCP 握手和重传的开销
101 | - 强调性能而不是数据完整性的场景可用 UDP
102 |
103 | ### 原始套接字
104 |
105 | ## 其他
106 |
107 | ### 关于端口
108 |
109 | - 端口取值范围是 0~65535
110 | - 1024 下的端口称之为“著名端口”或“周知端口”(留给 FTP HTTP SMTP 等著名服务使用的端口)
111 | - 自定义的服务通常不使用“著名端口”
--------------------------------------------------------------------------------
/day14-b/index.md:
--------------------------------------------------------------------------------
1 | # Day14-B 网络应用开发
2 |
3 | ## 发送邮件
4 |
5 | - SMTP(简单邮件传输协议):建立在 TCP 上的协议
6 | - Python 模块 `smtplib`
7 |
8 | ```python
9 | from smtplib import SMTP
10 | from email.header import Header
11 | from email.mime.text import MIMEText
12 |
13 |
14 | def main():
15 | # 请自行修改下面的邮件发送者和接收者
16 | sender = 'abcdefg@126.com'
17 | receivers = ['uvwxyz@qq.com', 'uvwxyz@126.com']
18 | message = MIMEText('用Python发送邮件的示例代码.', 'plain', 'utf-8')
19 | message['From'] = Header('王大锤', 'utf-8')
20 | message['To'] = Header('骆昊', 'utf-8')
21 | message['Subject'] = Header('示例代码实验邮件', 'utf-8')
22 | smtper = SMTP('smtp.126.com')
23 | # 请自行修改下面的登录口令
24 | smtper.login(sender, 'secretpass')
25 | smtper.sendmail(sender, receivers, message.as_string())
26 | print('邮件发送完成!')
27 |
28 |
29 | if __name__ == '__main__':
30 | main()
31 | ```
32 |
33 | ## 发送短信
34 |
35 | - 短信平台,调用 API 接口
--------------------------------------------------------------------------------
/img/day01/task-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/img/day01/task-2.png
--------------------------------------------------------------------------------
/img/day11/file-open-mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/img/day11/file-open-mode.png
--------------------------------------------------------------------------------
/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/img/icon.png
--------------------------------------------------------------------------------
/res/01.django_single_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/01.django_single_server.png
--------------------------------------------------------------------------------
/res/02.django_dedicated_db_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/02.django_dedicated_db_server.png
--------------------------------------------------------------------------------
/res/03.django_dedicated_static_server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/03.django_dedicated_static_server.png
--------------------------------------------------------------------------------
/res/04.django_load_balance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/04.django_load_balance.png
--------------------------------------------------------------------------------
/res/05.django_massive_cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/05.django_massive_cluster.png
--------------------------------------------------------------------------------
/res/Celery_RabitMQ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/Celery_RabitMQ.png
--------------------------------------------------------------------------------
/res/Producer-Broker-Consumer-Arrangement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/Producer-Broker-Consumer-Arrangement.png
--------------------------------------------------------------------------------
/res/abstraction-view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/abstraction-view.png
--------------------------------------------------------------------------------
/res/algorithm_complexity_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/algorithm_complexity_1.png
--------------------------------------------------------------------------------
/res/algorithm_complexity_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/algorithm_complexity_2.png
--------------------------------------------------------------------------------
/res/alipay_web_developer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/alipay_web_developer.png
--------------------------------------------------------------------------------
/res/aliyun-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/aliyun-certificate.png
--------------------------------------------------------------------------------
/res/aliyun-dnslist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/aliyun-dnslist.png
--------------------------------------------------------------------------------
/res/aliyun-domain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/aliyun-domain.png
--------------------------------------------------------------------------------
/res/aliyun-keeprecord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/aliyun-keeprecord.png
--------------------------------------------------------------------------------
/res/aliyun-resolve-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/aliyun-resolve-settings.png
--------------------------------------------------------------------------------
/res/app_folder_arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/app_folder_arch.png
--------------------------------------------------------------------------------
/res/builtin-middlewares.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/builtin-middlewares.png
--------------------------------------------------------------------------------
/res/celery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/celery.png
--------------------------------------------------------------------------------
/res/celery_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/celery_architecture.png
--------------------------------------------------------------------------------
/res/class-and-object.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/class-and-object.png
--------------------------------------------------------------------------------
/res/click-jacking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/click-jacking.png
--------------------------------------------------------------------------------
/res/company_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/company_architecture.png
--------------------------------------------------------------------------------
/res/concurrency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/concurrency.png
--------------------------------------------------------------------------------
/res/deployment_pipelines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/deployment_pipelines.png
--------------------------------------------------------------------------------
/res/django-middleware.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/django-middleware.png
--------------------------------------------------------------------------------
/res/django-mtv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/django-mtv.png
--------------------------------------------------------------------------------
/res/django_request_response_cycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/django_request_response_cycle.png
--------------------------------------------------------------------------------
/res/docker_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/docker_logo.png
--------------------------------------------------------------------------------
/res/docker_vs_vm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/docker_vs_vm.png
--------------------------------------------------------------------------------
/res/encapsulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/encapsulation.png
--------------------------------------------------------------------------------
/res/er-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/er-graph.png
--------------------------------------------------------------------------------
/res/git_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/git_logo.png
--------------------------------------------------------------------------------
/res/git_repository.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/git_repository.png
--------------------------------------------------------------------------------
/res/gitignore_io.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/gitignore_io.png
--------------------------------------------------------------------------------
/res/greedy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/greedy.png
--------------------------------------------------------------------------------
/res/hadoop_ecosystem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/hadoop_ecosystem.png
--------------------------------------------------------------------------------
/res/http-request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/http-request.png
--------------------------------------------------------------------------------
/res/http-response.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/http-response.png
--------------------------------------------------------------------------------
/res/int-is-comparation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/int-is-comparation.png
--------------------------------------------------------------------------------
/res/jenkins_new_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/jenkins_new_project.png
--------------------------------------------------------------------------------
/res/modularity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/modularity.png
--------------------------------------------------------------------------------
/res/multi-inheritance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/multi-inheritance.png
--------------------------------------------------------------------------------
/res/mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/mvc.png
--------------------------------------------------------------------------------
/res/oauth2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/oauth2.png
--------------------------------------------------------------------------------
/res/object-roles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/object-roles.png
--------------------------------------------------------------------------------
/res/objects-collaborate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/objects-collaborate.png
--------------------------------------------------------------------------------
/res/objects-lifetime.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/objects-lifetime.png
--------------------------------------------------------------------------------
/res/power-designer-pdm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/power-designer-pdm.png
--------------------------------------------------------------------------------
/res/pycharm-activate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-activate.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-1.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-2.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-3.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-4.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-5.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-6.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-7.png
--------------------------------------------------------------------------------
/res/pycharm-comm-django-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-comm-django-8.png
--------------------------------------------------------------------------------
/res/pycharm-create-launcher-script.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-create-launcher-script.png
--------------------------------------------------------------------------------
/res/pycharm-import-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-import-settings.png
--------------------------------------------------------------------------------
/res/pycharm-new-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-new-project.png
--------------------------------------------------------------------------------
/res/pycharm-plugins.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-plugins.png
--------------------------------------------------------------------------------
/res/pycharm-prof-django-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-prof-django-2.png
--------------------------------------------------------------------------------
/res/pycharm-prof-django-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-prof-django-3.png
--------------------------------------------------------------------------------
/res/pycharm-set-ui-theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-set-ui-theme.png
--------------------------------------------------------------------------------
/res/pycharm-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-welcome.png
--------------------------------------------------------------------------------
/res/pycharm-workspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pycharm-workspace.png
--------------------------------------------------------------------------------
/res/pylint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/pylint.png
--------------------------------------------------------------------------------
/res/python-bj-salary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-bj-salary.png
--------------------------------------------------------------------------------
/res/python-built-in-functions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-built-in-functions.png
--------------------------------------------------------------------------------
/res/python-cd-salary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-cd-salary.png
--------------------------------------------------------------------------------
/res/python-job-all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-job-all.png
--------------------------------------------------------------------------------
/res/python-job-chengdu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-job-chengdu.png
--------------------------------------------------------------------------------
/res/python-salary-beijing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary-beijing.png
--------------------------------------------------------------------------------
/res/python-salary-chengdu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary-chengdu.png
--------------------------------------------------------------------------------
/res/python-salary-hangzhou.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary-hangzhou.png
--------------------------------------------------------------------------------
/res/python-salary-shanghai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary-shanghai.png
--------------------------------------------------------------------------------
/res/python-salary-shenzhen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary-shenzhen.png
--------------------------------------------------------------------------------
/res/python-salary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-salary.png
--------------------------------------------------------------------------------
/res/python-str-join.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-str-join.png
--------------------------------------------------------------------------------
/res/python-top-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-top-10.png
--------------------------------------------------------------------------------
/res/python-tutor-visualize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-tutor-visualize.png
--------------------------------------------------------------------------------
/res/python-tutor-visualize2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python-tutor-visualize2.png
--------------------------------------------------------------------------------
/res/python_jobs_chengdu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python_jobs_chengdu.png
--------------------------------------------------------------------------------
/res/python_salary_chengdu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python_salary_chengdu.png
--------------------------------------------------------------------------------
/res/python_salary_guangzhou.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/python_salary_guangzhou.png
--------------------------------------------------------------------------------
/res/rbac-basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/rbac-basic.png
--------------------------------------------------------------------------------
/res/rbac-full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/rbac-full.png
--------------------------------------------------------------------------------
/res/redmine_new_issue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/redmine_new_issue.png
--------------------------------------------------------------------------------
/res/requirements_by_xmind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/requirements_by_xmind.png
--------------------------------------------------------------------------------
/res/result-of-dis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/result-of-dis.png
--------------------------------------------------------------------------------
/res/selenium-ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/selenium-ide.png
--------------------------------------------------------------------------------
/res/selenium_ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/selenium_ide.png
--------------------------------------------------------------------------------
/res/shopping-pdm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/shopping-pdm.png
--------------------------------------------------------------------------------
/res/the-daily-scrum-in-the-sprint-cycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/the-daily-scrum-in-the-sprint-cycle.png
--------------------------------------------------------------------------------
/res/uml-class-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/uml-class-diagram.png
--------------------------------------------------------------------------------
/res/uml-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/uml-graph.png
--------------------------------------------------------------------------------
/res/uml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/uml.png
--------------------------------------------------------------------------------
/res/web-application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/web-application.png
--------------------------------------------------------------------------------
/res/web-queue-worker-physical.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/web-queue-worker-physical.png
--------------------------------------------------------------------------------
/res/zen-of-python.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JalanJiang/python-100-practice/32b460465b1e46bf3e37b960733964ecfe2d6ab4/res/zen-of-python.png
--------------------------------------------------------------------------------
/rule.md:
--------------------------------------------------------------------------------
1 | - Martin Fowler 先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”
2 | - 尽量减少对全局变量的使用:
3 | 1. 全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用
4 | 2. 全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被 [垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))
5 | 3. 减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措
6 | 4. 对 [迪米特法则](https://zh.wikipedia.org/zh-hans/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B) 的践行
--------------------------------------------------------------------------------