├── .gitattributes
├── README.md
├── _config.yml
├── main.py
├── pics
├── biaoqingbao1.jpeg
├── biaoqingbao2.jpeg
├── cute-chuoni.jpg
├── cute-dog-question-gif.gif
├── cute-fly-pink.png
├── cute-fly.png
├── cute-gif.gif
├── cute-meat.jpg
├── cute-qinqin.jpg
├── cute-question.gif
├── cute-x1.png
├── cute-x2.png
├── cute-x3.png
├── cute-x4.png
├── cute-y1.png
├── cute-y2.png
├── cute-y3.png
├── cute-y4.png
├── cute1.jpg
├── emoj.gif
└── tit.png
├── step0-Python-Script
├── README.md
├── img2char
│ ├── demo.png
│ ├── main.py
│ └── readme.txt
├── imgDeal
│ ├── main.py
│ └── readme.txt
├── timer
│ ├── main.py
│ └── readme.txt
└── youdaoAPI
│ ├── main.py
│ └── readme.txt
├── step1-Python-basis
├── Basic Grammar
│ ├── Data-Type.md
│ ├── README.md
│ ├── dict-set.md
│ ├── for-while.md
│ ├── if-else.md
│ └── list-tuple.md
├── Function
│ └── README.md
├── Part-One.md
├── Part-Three.md
├── Part-Two.md
├── PyCharm安装教程.md
├── README.md
├── VS-Code安装教程.md
├── backup.md
└── pics
│ ├── 1.1.png
│ ├── 1.10.png
│ ├── 1.11.png
│ ├── 1.12.png
│ ├── 1.13.png
│ ├── 1.14.png
│ ├── 1.15.png
│ ├── 1.16.png
│ ├── 1.17.png
│ ├── 1.18.png
│ ├── 1.19.png
│ ├── 1.2.png
│ ├── 1.20.png
│ ├── 1.21.png
│ ├── 1.22.png
│ ├── 1.23.png
│ ├── 1.24.png
│ ├── 1.25.png
│ ├── 1.26.png
│ ├── 1.27.png
│ ├── 1.28.png
│ ├── 1.3.png
│ ├── 1.4.png
│ ├── 1.41111.png
│ ├── 1.5.png
│ ├── 1.6.png
│ ├── 1.7.png
│ ├── 1.8.png
│ ├── 1.9.png
│ ├── 1.vs1.png
│ ├── 1.vs2.png
│ ├── 1.vs3.png
│ ├── 1.vs4.png
│ ├── 1.vs5.png
│ ├── 1.vs6.png
│ ├── 1.vs7.png
│ ├── 1.vs8.png
│ ├── 2.1.png
│ ├── 2.10.png
│ ├── 2.11.png
│ ├── 2.12.png
│ ├── 2.2.png
│ ├── 2.3.png
│ ├── 2.4.png
│ ├── 2.5.png
│ ├── 2.6.png
│ ├── 2.7.png
│ ├── 2.8.png
│ ├── 2.9.png
│ ├── 4.3.png
│ ├── 5.1.png
│ ├── 5.2.png
│ ├── 6.0.png
│ └── readme.md
├── step2-Pygame
├── README.md
├── files
│ ├── README.md
│ └── pie游戏.py
└── pics
│ ├── 1.1.png
│ ├── 1.2.png
│ ├── 1.3.png
│ ├── 1.4.png
│ ├── 1.5.png
│ ├── 1.6.gif
│ ├── 1.7.png
│ ├── 1.8.png
│ ├── 1.9.gif
│ └── readme.md
├── step3-PyQt5-GUI
└── README.md
├── step4-Algorithm
├── Discrete-Mathematics
│ └── README.md
├── README.md
├── code
│ ├── Dijkstra之解决图中任意两点间最短距离.py
│ └── input.jpg
└── pics
│ ├── README.md
│ └── binarytree.jpg
├── step5-Python-web
├── Django
│ ├── Django-Ubuntu-BlogWeb
│ │ ├── README.md
│ │ └── 用户管理功能完善.md
│ └── Django-Win10-DiaryWeb
│ │ └── README.md
├── Flask
│ ├── README.md
│ └── project
│ │ ├── app.py
│ │ ├── forms.py
│ │ ├── static
│ │ ├── css
│ │ │ ├── bootstrap.min.css
│ │ │ └── index.css
│ │ ├── img
│ │ │ └── news
│ │ │ │ ├── 1.png
│ │ │ │ ├── 2.png
│ │ │ │ ├── 3.png
│ │ │ │ ├── 4.png
│ │ │ │ ├── 5.png
│ │ │ │ ├── 6.png
│ │ │ │ ├── 7.png
│ │ │ │ ├── 8.png
│ │ │ │ └── 9.png
│ │ └── js
│ │ │ ├── bootstrap.min.js
│ │ │ └── jquery.min.js
│ │ └── templates
│ │ ├── admin
│ │ ├── add.html
│ │ ├── admin_base.html
│ │ ├── index.html
│ │ └── update.html
│ │ ├── base.html
│ │ ├── cat.html
│ │ ├── detail.html
│ │ └── index.html
├── README.md
├── Tornado
│ ├── README.md
│ ├── async_demo
│ │ ├── requirements.txt
│ │ ├── server.py
│ │ ├── static
│ │ │ ├── book.js
│ │ │ └── jquery-3.3.1.min.js
│ │ └── templates
│ │ │ └── index.html
│ └── sync_demo
│ │ ├── requirements.txt
│ │ ├── server.py
│ │ ├── static
│ │ ├── book.js
│ │ └── jquery-3.3.1.min.js
│ │ └── templates
│ │ └── index.html
├── helloflask.py
└── urls和视图.md
├── step6-Crawl
├── Crawler-system-project
│ └── README.md
├── Learn-from-Projects
│ ├── README.md
│ ├── maoyanTop100.py
│ ├── 爬取bilibili单页视频信息.py
│ ├── 爬取白蛇缘起豆瓣影评.py
│ ├── 爬取纽约市景点信息.py
│ └── 通过访问手机端爬取58同城商品信息.py
├── RE
│ └── README.md
├── README.md
├── Regular-Expression
│ └── README.md
├── python-re实例.md
├── sicnu-student-crawl
│ ├── README.md
│ ├── college_list.csv
│ ├── college_list.py
│ ├── crawl.py
│ └── student.py
└── 正则表达式
│ └── README.md
├── step7-Data-Analysis
├── README.md
└── docs
│ ├── 01-pre.md
│ ├── 02-IPython-and-Jupyter notebook.md
│ ├── 03-Python-base.md
│ ├── 04-Python-advanced.md
│ ├── 05-NumPy-base.md
│ └── numpy 模块
│ └── README.md
└── step8-Machine-Learning
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | pycharm5.0.3.zip filter=lfs diff=lfs merge=lfs -text
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 | ---
6 |
7 | ***简介 :** 一个 Python 全系列的笔记。笔者以一个初学者的立场,用笔记、分享等形式来给大家总结一些东西。总之,Python为基础,让我们向全栈出发!(如果本文有任何问题,欢迎发起 Issues,如果本文帮助了你,欢迎 Star⭐)*
8 |
9 |
10 |

11 |
12 |
13 | ---
14 |
15 | 💌 这里有什么?我将从以下几个方面带你一步一步走向 Python 全栈:
16 |
17 |
18 |
19 | 📖 **[Step0:Python 脚本](step0-Python-Script)**
20 |
21 |
22 | 详情
23 |
26 |
27 |
28 | 📖 **[Step1:Python 基础](step1-Python-basis)**
29 |
30 |
31 | 详情
32 |
33 |
34 | - 正则表达式(Regular Expression, RE)
35 |
36 |
37 |
38 | 📖 **[Step2:Pygame 游戏编程](step2-Pygame)**
39 |
40 | 📖 **[Step3:PyQt5 GUI编程](step3-PyQt5-GUI)**
41 |
42 | 📖 **[Step4:Python 数据结构与算法](step4-Algorithm)**
43 |
44 | 📖 **[Step5:Python Web](step5-Python-web)**
45 |
46 |
47 | 详情
48 |
49 | - (前导知识点:前端 / 计算机网络)
50 | - 正则表达式(Regular Expression, RE)
51 |
52 |
53 |
54 | 📖 **[Step6:Python 网络爬虫](step6-Crawl)**
55 |
56 | 📖 **[Step7:数据分析及可视化](step7-Data-Analysis)**
57 |
58 | 📖 **[Step8:Python 机器学习](step8-Machine-Learning)**
59 |
60 | ---
61 |
62 |
68 |
69 | ---
70 |
71 |
72 |
73 | 序
74 |
75 |
76 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | count = 0
4 | while True:
5 | count += 1
6 | print(str(count) + '个人没睡')
7 | time.sleep(1)
8 |
--------------------------------------------------------------------------------
/pics/biaoqingbao1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/biaoqingbao1.jpeg
--------------------------------------------------------------------------------
/pics/biaoqingbao2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/biaoqingbao2.jpeg
--------------------------------------------------------------------------------
/pics/cute-chuoni.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-chuoni.jpg
--------------------------------------------------------------------------------
/pics/cute-dog-question-gif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-dog-question-gif.gif
--------------------------------------------------------------------------------
/pics/cute-fly-pink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-fly-pink.png
--------------------------------------------------------------------------------
/pics/cute-fly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-fly.png
--------------------------------------------------------------------------------
/pics/cute-gif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-gif.gif
--------------------------------------------------------------------------------
/pics/cute-meat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-meat.jpg
--------------------------------------------------------------------------------
/pics/cute-qinqin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-qinqin.jpg
--------------------------------------------------------------------------------
/pics/cute-question.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-question.gif
--------------------------------------------------------------------------------
/pics/cute-x1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-x1.png
--------------------------------------------------------------------------------
/pics/cute-x2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-x2.png
--------------------------------------------------------------------------------
/pics/cute-x3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-x3.png
--------------------------------------------------------------------------------
/pics/cute-x4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-x4.png
--------------------------------------------------------------------------------
/pics/cute-y1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-y1.png
--------------------------------------------------------------------------------
/pics/cute-y2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-y2.png
--------------------------------------------------------------------------------
/pics/cute-y3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-y3.png
--------------------------------------------------------------------------------
/pics/cute-y4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute-y4.png
--------------------------------------------------------------------------------
/pics/cute1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/cute1.jpg
--------------------------------------------------------------------------------
/pics/emoj.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/emoj.gif
--------------------------------------------------------------------------------
/pics/tit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/pics/tit.png
--------------------------------------------------------------------------------
/step0-Python-Script/README.md:
--------------------------------------------------------------------------------
1 | # 🏹 Python 脚本
2 |
3 | 脚本的本质就是一个完整的应用程序。而我们单独将 Python 脚本 单开一节主要是为了存放一些程序代码。因为我们后面已经有了 Pygame 和 GUI 两节,所以这一节的脚本代码只会涉及到 Python 原生解释器运行的程序。
4 |
5 | + **本节项目结构**
6 |
7 | ```
8 | ├── 项目一
9 | │ ├── readme.txt # how to run?(介绍及运行说明)
10 | │ ├── main.py # main entrance(程序运行主入口)
11 | │ ├── xxx.py # assistant program(辅助程序,数量不定)
12 | │ ├── assets # 资源存放文件夹
13 | │ │ ├── ...
14 | ├── 项目二
15 | │ ├── readme.txt # how to run?(介绍及运行说明)
16 | │ ├── main.py # main entrance(程序运行主入口)
17 | │ ├── xxx.py # assistant program(辅助程序,数量不定)
18 | │ ├── assets # 资源存放文件夹
19 | │ │ ├── ...
20 | ├── ...
21 | ```
22 |
23 | ### 🔍 相关索引
24 |
25 | + **[定时器](timer)**
26 |
27 | + **[图片转字符画](img2char)**
28 |
29 | + **[有道翻译接口](youdaoAPI)**
30 |
31 | + **[图片分辨率及大小处理](imgDeal)**
32 |
33 |
34 |
35 | <- 未完待续 ->
36 |
37 |
--------------------------------------------------------------------------------
/step0-Python-Script/img2char/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step0-Python-Script/img2char/demo.png
--------------------------------------------------------------------------------
/step0-Python-Script/img2char/main.py:
--------------------------------------------------------------------------------
1 | from PIL import Image
2 | import argparse
3 |
4 | #命令行输入参数处理
5 | parser = argparse.ArgumentParser()
6 |
7 | parser.add_argument('file') # 输入文件
8 | parser.add_argument('-o', '--output') # 输出文件
9 | parser.add_argument('--width', type=int, default=80) # 输出字符画宽
10 | parser.add_argument('--height', type=int, default=80) # 输出字符画高
11 |
12 | #获取参数
13 | args = parser.parse_args()
14 |
15 | IMG = args.file
16 | WIDTH = args.width
17 | HEIGHT = args.height
18 | OUTPUT = args.output
19 |
20 | ascii_char = list(
21 | "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
22 |
23 | # 将256灰度映射到70个字符上
24 |
25 |
26 | def get_char(r, g, b, alpha=256):
27 | if alpha == 0:
28 | return ' '
29 | length = len(ascii_char)
30 | gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
31 |
32 | unit = (256.0 + 1)/length
33 | return ascii_char[int(gray/unit)]
34 |
35 |
36 | if __name__ == '__main__':
37 |
38 | im = Image.open(IMG)
39 | im = im.resize((WIDTH, HEIGHT), Image.NEAREST)
40 |
41 | txt = ""
42 |
43 | for i in range(HEIGHT):
44 | for j in range(WIDTH):
45 | txt += get_char(*im.getpixel((j, i)))
46 | txt += '\n'
47 |
48 | print(txt)
49 |
50 | #字符画输出到文件
51 | if OUTPUT:
52 | with open(OUTPUT, 'w') as f:
53 | f.write(txt)
54 | else:
55 | with open("output.txt", 'w') as f:
56 | f.write(txt)
57 |
--------------------------------------------------------------------------------
/step0-Python-Script/img2char/readme.txt:
--------------------------------------------------------------------------------
1 | 功能:传入一张图片为参数,控制台会显示这张图片的字符图案,并在当前文件夹下生成此字符图案的 output.txt。
2 |
3 | 依赖模块:Pillow
4 | pip install Pillow
5 |
6 | 运行:python main.py demo.png
--------------------------------------------------------------------------------
/step0-Python-Script/imgDeal/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PIL import Image
3 |
4 |
5 | input_file = "./222.jpg"
6 | output_file = "./output.jpg"
7 |
8 | im = Image.open(input_file)
9 | size = os.path.getsize(input_file) / 1024
10 | w, h = im.size
11 |
12 | # 压缩图片
13 | while size > 100:
14 | w, h = round(w * 0.9), round(h * 0.9)
15 | im = im.resize((w, h), Image.ANTIALIAS)
16 | im.save(output_file)
17 | size = os.path.getsize(output_file) / 1024
18 |
19 | # 修改分辨率
20 | im.save(output_file, dpi=(400, 720))
21 |
--------------------------------------------------------------------------------
/step0-Python-Script/imgDeal/readme.txt:
--------------------------------------------------------------------------------
1 | 功能:输出指定分辨率和大小的图片。
2 |
3 | 运行:python main.py
4 |
--------------------------------------------------------------------------------
/step0-Python-Script/timer/main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 | import time
3 |
4 | old_time = ''
5 | flag = 1
6 | def timer(interval):
7 | global flag
8 | global old_time
9 | if flag:
10 | old_time = time.strftime('%S', time.localtime(time.time()))
11 | flag = 0
12 | now_time = time.strftime('%S', time.localtime(time.time()))
13 | if int(old_time) >= 60-interval:
14 | if int(old_time)+interval-60 == int(now_time):
15 | print(time.strftime('%H:%M:%S', time.localtime(time.time())))
16 | old_time = now_time
17 | else:
18 | if int(now_time) - int(old_time) == interval:
19 | print(time.strftime('%H:%M:%S', time.localtime(time.time())))
20 | old_time = now_time
21 |
22 | '''
23 | Python 定时器:
24 |
25 | 输入间隔单位时间(单位s)
26 | 每到单位时间会执行一次函数,并显示当前时间
27 | '''
28 | if __name__ == "__main__":
29 | interval = int(input('请输入要间隔的时间:'))
30 | while True:
31 | timer(interval)
32 |
--------------------------------------------------------------------------------
/step0-Python-Script/timer/readme.txt:
--------------------------------------------------------------------------------
1 | 功能:输入一个间隔时间(int),控制台会按照输入的间隔时间打印当前时间。
2 |
3 | 如:
4 | --input--
5 | $ 5
6 | --output--
7 | 13:12:52
8 | 13:12:57
9 | 13:13:02
10 | ...
11 | (Ctrl+C, 执行按键中断 KeyboardInterrupt 退出)
12 |
13 | 运行:python main.py
--------------------------------------------------------------------------------
/step0-Python-Script/youdaoAPI/main.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import urllib.parse
3 | import json
4 |
5 | def get_translate(word=None):
6 | if word == None:
7 | return
8 | else:
9 | url = 'http://fanyi.youdao.com/translate'
10 | data = {
11 | 'from':'AUTO',
12 | 'to':'AUTO',
13 | 'smartresult':'dict',
14 | 'client':'fanyideskweb',
15 | 'salt':'1500092479607',
16 | 'sign':'c98235a85b213d482b8e65f6b1065e26',
17 | 'doctype':'json',
18 | 'version':'2.1',
19 | 'keyfrom':'fanyi.web',
20 | 'action':'FY_BY_CL1CKBUTTON',
21 | 'typoResult':'true'
22 | }
23 |
24 | data['i'] = word
25 | data = urllib.parse.urlencode(data).encode('utf8')
26 | response = urllib.request.urlopen(url,data)
27 | html = response.read().decode('utf8')
28 | content = json.loads(html)
29 | print('翻译结果: %s '% (content['translateResult'][0][0]['tgt']))
30 |
31 | if __name__ == '__main__':
32 | # get_translate('我爱你')
33 | strwords = input('输入文本:')
34 | get_translate(strwords)
--------------------------------------------------------------------------------
/step0-Python-Script/youdaoAPI/readme.txt:
--------------------------------------------------------------------------------
1 | 功能:输入待翻译文本,一段时间后(根据网络响应速度)输出有道翻译提供的结果。
2 |
3 | 如:
4 | --input--
5 | $ 输入文本:我爱你
6 | --output--
7 | $ 翻译结果:I love you
8 |
9 | 运行:python main.py
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/Data-Type.md:
--------------------------------------------------------------------------------
1 | ### Python 数据类型
2 | + 整数
3 | + 浮点数
4 | + 字符串
5 |
6 | [字符串]()是以单引号`'`或双引号`"`括起来的任意文本,比如`'abc'`,`"xyz"`等等。
7 | ```python
8 | >>>print('abc')
9 | abc
10 | >>>print("xyz")
11 | xyz
12 | ```
13 | 转义字符 [\\]() 可以转义很多字符,比如 [\n]() 表示换行, [\t]() 表示制表符,字符 [\\]() 本身也要转义,所以 [\\\\]() 表示的字符就是 [\\]()
14 | ```python
15 | >>>print('\\')
16 | \
17 | >>>print('\\\\')
18 | \\
19 | ```
20 | 如果字符串里面有很多字符都需要转义,就需要加很多 [\\]() ,为了简化,[Python]()还允许用 [r' ']() 表示 [' ']() 内部的字符串默认不转义:
21 | ```python
22 | >>>print('\\\t\\')
23 | \ \
24 | >>>print(r'\\\t\\')
25 | \\\t\\
26 | ```
27 | 如果字符串内部有很多换行,用 [\n]() 写在一行里不好阅读,为了简化,[Python]()允许用 ['''...''']() 的格式表示多行内容:
28 | ```python
29 | >>>print('''line1
30 | line2
31 | line3''')
32 | line1
33 | line2
34 | line3
35 | ```
36 | + 布尔值
37 |
38 | 一个布尔值只有[True]()、[False]()两种值,要么是[True](),要么是[False](),在[Python]()中,可以直接用[True]()、[False]()表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
39 | ```python
40 | >>>True
41 | True
42 | >>>False
43 | False
44 | >>>print(True)
45 | True
46 | >>>3 > 2
47 | True
48 | >>>print(3 > 5)
49 | False
50 | ```
51 | 布尔值可以用[and与]()、[or或]()和[not非]()运算。
52 | ```python
53 | >>>True and True
54 | True
55 | >>>True and False
56 | False
57 | >>>False and False
58 | False
59 | >>>2 > 1 and 3 > 1
60 | True
61 | >>> True or True
62 | True
63 | >>> True or False
64 | True
65 | >>> False or False
66 | False
67 | >>> 5 > 3 or 1 > 3
68 | True
69 | >>> not True
70 | False
71 | >>> not False
72 | True
73 | >>> not 1 > 2
74 | True
75 | ```
76 | + 空值
77 |
78 | 空值是[Python]()里一个特殊的值,用[None]()表示。[None]()不能理解为[0](),因为[0]()是有意义的,而[None]()是一个特殊的空值。
79 | ---
80 | ### 变量
81 | 变量可以是任意数据类型,在程序中,变量用其变量名表示。变量名必须是大小写英文、数字和`_`的组合,且不能用数字开头,比如:
82 | ```python
83 | >>>a = 1 #变量a是一个整数
84 | >>>name_1 = 'fmw' #变量name_1是一个字符串
85 | >>>Flag = True #变量Flag是一个布尔值True
86 | ```
87 | 等号 [=]() 是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
88 | ```python
89 | >>>a = 123 #变量a是一个整数
90 | >>>a = 'abc' #变量a变为字符串
91 | ```
92 | ---
93 | ### 常量
94 | 通常用全部大写的变量名表示
95 | ```python
96 | >>>PI = 3.14
97 | ```
98 | 除法 [/]() :
99 | ```python
100 | >>>10 / 3
101 | 3.3333333333333335
102 | ```
103 | [/]() 除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:
104 | ```python
105 | >>>9 / 3
106 | 3.0
107 | ```
108 | 除法 [//]() ,计算结果为整数部分:
109 | ```python
110 | >>>9 // 3
111 | 3
112 | >>>10 // 3
113 | 3
114 | ```
115 | 求余 [%]() :
116 | ```python
117 | >>>9 % 3
118 | 0
119 | >>>10 % 3
120 | 1
121 | ```
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/README.md:
--------------------------------------------------------------------------------
1 | # ⚡Python基础
2 | *这是一个快捷目录栏*
3 | + [数据类型和变量](#Python数据类型)
4 |
5 | + [使用list和tuple](#)
6 |
7 | + [条件判断](#)
8 |
9 | + [循环](#)
10 |
11 | + [使用dict和set](#)
12 |
13 | ---
14 |
15 | # Python数据类型
16 | + 整数
17 | + 浮点数
18 | + 字符串
19 |
20 | [字符串]()是以单引号`'`或双引号`"`括起来的任意文本,比如`'abc'`,`"xyz"`等等。
21 | ```python
22 | >>>print('abc')
23 | abc
24 | >>>print("xyz")
25 | xyz
26 | ```
27 | 转义字符 [\\]() 可以转义很多字符,比如 [\n]() 表示换行, [\t]() 表示制表符,字符 [\\]() 本身也要转义,所以 [\\\\]() 表示的字符就是 [\\]()
28 | ```python
29 | >>>print('\\')
30 | \
31 | >>>print('\\\\')
32 | \\
33 | ```
34 | 如果字符串里面有很多字符都需要转义,就需要加很多 [\\]() ,为了简化,[Python]()还允许用 [r' ']() 表示 [' ']() 内部的字符串默认不转义:
35 | ```python
36 | >>>print('\\\t\\')
37 | \ \
38 | >>>print(r'\\\t\\')
39 | \\\t\\
40 | ```
41 | 如果字符串内部有很多换行,用 [\n]() 写在一行里不好阅读,为了简化,[Python]()允许用 ['''...''']() 的格式表示多行内容:
42 | ```python
43 | >>>print('''line1
44 | line2
45 | line3''')
46 | line1
47 | line2
48 | line3
49 | ```
50 | + 布尔值
51 |
52 | 一个布尔值只有[True]()、[False]()两种值,要么是[True](),要么是[False](),在[Python]()中,可以直接用[True]()、[False]()表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
53 | ```python
54 | >>>True
55 | True
56 | >>>False
57 | False
58 | >>>print(True)
59 | True
60 | >>>3 > 2
61 | True
62 | >>>print(3 > 5)
63 | False
64 | ```
65 | 布尔值可以用[and与]()、[or或]()和[not非]()运算。
66 | ```python
67 | >>>True and True
68 | True
69 | >>>True and False
70 | False
71 | >>>False and False
72 | False
73 | >>>2 > 1 and 3 > 1
74 | True
75 | >>> True or True
76 | True
77 | >>> True or False
78 | True
79 | >>> False or False
80 | False
81 | >>> 5 > 3 or 1 > 3
82 | True
83 | >>> not True
84 | False
85 | >>> not False
86 | True
87 | >>> not 1 > 2
88 | True
89 | ```
90 | + 空值
91 |
92 | 空值是[Python]()里一个特殊的值,用[None]()表示。[None]()不能理解为[0](),因为[0]()是有意义的,而[None]()是一个特殊的空值。
93 |
94 | ## 变量
95 | 变量可以是任意数据类型,在程序中,变量用其变量名表示。变量名必须是大小写英文、数字和`_`的组合,且不能用数字开头,比如:
96 | ```python
97 | >>>a = 1 #变量a是一个整数
98 | >>>name_1 = 'fmw' #变量name_1是一个字符串
99 | >>>Flag = True #变量Flag是一个布尔值True
100 | ```
101 | 等号 [=]() 是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
102 | ```python
103 | >>>a = 123 #变量a是一个整数
104 | >>>a = 'abc' #变量a变为字符串
105 | ```
106 |
107 | ## 常量
108 | 通常用全部大写的变量名表示
109 | ```python
110 | >>>PI = 3.14
111 | ```
112 | 除法 [/]() :
113 | ```python
114 | >>>10 / 3
115 | 3.3333333333333335
116 | ```
117 | [/]() 除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:
118 | ```python
119 | >>>9 / 3
120 | 3.0
121 | ```
122 | 除法 [//]() ,计算结果为整数部分:
123 | ```python
124 | >>>9 // 3
125 | 3
126 | >>>10 // 3
127 | 3
128 | ```
129 | 求余 [%]() :
130 | ```python
131 | >>>9 % 3
132 | 0
133 | >>>10 % 3
134 | 1
135 | ```
136 |
137 |
138 | [返回目录>>](#Python基础)
139 |
140 | ---
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/dict-set.md:
--------------------------------------------------------------------------------
1 | ### dict
2 | [Python]()内置了字典: [dict]() 的支持,[dict]() 全称dictionary,在其他语言中也称为 [map]() ,使用键-值(key-value)存储,具有极快的查找速度。
3 |
4 | 举个例子,假设要根据同学的名字查找对应的成绩,如果用[list]()实现,需要两个[list]():
5 | ```python
6 | names = ['fmw', 'zhang', 'li']
7 | scores = [95, 75, 85]
8 | ```
9 | 给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。
10 |
11 | 如果用 [dict]() 实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用Python写一个 [dict]() 如下:
12 | ```python
13 | >>> d = {'fmw': 95, 'zhang': 75, 'li': 85}
14 | >>> d['fmw']
15 | 95
16 | ```
17 | 把数据放入 [dict]() 的方法,除了初始化时指定外,还可以通过key放入:
18 | ```python
19 | >>> d['zhang'] = 67
20 | >>> d['zhang']
21 | 67
22 | ```
23 | 如果key不存在, [dict]() 就会报错:
24 | ```python
25 | >>> d['song']
26 | Traceback (most recent call last):
27 | File "", line 1, in
28 | KeyError: 'song'
29 | ```
30 | 要避免key不存在的错误,有两种办法,一是通过 [in]() 判断key是否存在:
31 | ```python
32 | >>> 'song' in d
33 | False
34 | ```
35 | 二是通过 [dict]() 提供的 [get()]() 方法,如果key不存在,可以返回None,或者自己指定的value:
36 | ```python
37 | >>> d.get('song')
38 | >>> d.get('song', -1)
39 | -1
40 | ```
41 | > 注意:返回`None`的时候Python的交互环境不显示结果。
42 |
43 | 要删除一个key,用 [pop(key)]() 方法,对应的value也会从 [dict]() 中删除:
44 | ```python
45 | >>> d.pop('zhang')
46 | 75
47 | >>> d
48 | {'fmw': 95, 'li': 85}
49 | ```
50 | 和 [list]() 比较,[dict]() 有以下几个特点:
51 |
52 | 1. 查找和插入的速度极快,不会随着key的增加而变慢;
53 | 1. 需要占用大量的内存,内存浪费多。
54 |
55 | 而 [list]() 相反:
56 |
57 | 1. 查找和插入的时间随着元素的增加而增加;
58 | 1. 占用空间小,浪费内存很少。
59 |
60 | 所以,[dict]()是用空间来换取时间的一种方法。
61 |
62 | ---
63 | ### set
64 | [set]() 和 [dict]() 类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在 [set]() 中,没有重复的key。
65 |
66 | 要创建一个 [set]() ,需要提供一个[list]()作为输入集合:
67 | ```python
68 | >>> s = set([1, 2, 3])
69 | >>> s
70 | {1, 2, 3}
71 | ```
72 | 注意,传入的参数[[1, 2, 3]]()是一个list,而显示的[{1, 2, 3}]()只是告诉你这个 [set]() 内部有1,2,3这3个元素,显示的顺序也不表示 [set]() 是有序的。。
73 |
74 | 重复元素在 [set]() 中自动被过滤:
75 | ```python
76 | >>> s = set([1, 1, 2, 2, 3, 3])
77 | >>> s
78 | {1, 2, 3}
79 | ```
80 | 通过 [add(key)]() 方法可以添加元素到 [set]() 中,可以重复添加,但不会有效果:
81 | ```python
82 | >>> s.add(4)
83 | >>> s
84 | {1, 2, 3, 4}
85 | >>> s.add(4)
86 | >>> s
87 | {1, 2, 3, 4}
88 | ```
89 | 通过 [remove(key)]() 方法可以删除元素:
90 | ```python
91 | >>> s.remove(4)
92 | >>> s
93 | {1, 2, 3}
94 | ```
95 | [set]() 可以看成数学意义上的无序和无重复元素的集合,因此,两个 [set]() 可以做数学意义上的交集、并集等操作:
96 | ```python
97 | >>> s1 = set([1, 2, 3])
98 | >>> s2 = set([2, 3, 4])
99 | >>> s1 & s2
100 | {2, 3}
101 | >>> s1 | s2
102 | {1, 2, 3, 4}
103 | ```
104 | [set]() 和 [dict]() 的唯一区别仅在于没有存储对应的value,但是,[set]() 的原理和 [dict]() 一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证 [set]() 内部“不会有重复元素”。
105 |
106 | ---
107 | ### 不可变对象
108 | 对于可变对象,比如[list](),对[list]()进行操作,[list]()内部的内容是会变化的,比如:
109 | ```python
110 | >>> a = ['c', 'b', 'a']
111 | >>> a.sort()
112 | >>> a
113 | ['a', 'b', 'c']
114 | ```
115 | 而对于不可变对象,比如 [str](),对 [str]() 进行操作呢:
116 | ```python
117 | >>> a = 'abc'
118 | >>> a.replace('a', 'A')
119 | 'Abc'
120 | >>> a
121 | 'abc'
122 | ```
123 | 虽然字符串有个 [replace()]()方法,也确实变出了['Abc'](),但变量a最后仍是['abc']()
124 | ```python
125 | >>> a = 'abc'
126 | >>> b = a.replace('a', 'A')
127 | >>> b
128 | 'Abc'
129 | >>> a
130 | 'abc'
131 | ```
132 |
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/for-while.md:
--------------------------------------------------------------------------------
1 | ### 循环
2 | [Python]()的循环有两种,一种是 [for...in]() 循环,依次把[list]()或[tuple]()中的每个元素迭代出来,看例子:
3 | ```python
4 | names = ['Michael', 'Bob', 'Tracy']
5 | for name in names:
6 | print(name)
7 | ```
8 | 再比如我们想计算1-10的整数之和,可以用一个sum变量做累加:
9 | ```python
10 | sum = 0
11 | for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
12 | sum = sum + x
13 | print(sum)
14 | ```
15 | [Python]()提供一个 [range()]() 函数,可以生成一个整数序列,[range(101)]() 就可以生成0-100的整数序列,计算如下:
16 | ```python
17 | sum = 0
18 | for x in range(101):
19 | sum = sum + x
20 | print(sum)
21 | ```
22 | 第二种循环是 [while]() 循环,只要条件满足,就不断循环,条件不满足时退出循环。比如我们要计算100以内所有奇数之和,可以用 [while]() 循环实现:
23 | ```python
24 | sum = 0
25 | n = 99
26 | while n > 0:
27 | sum = sum + n
28 | n = n - 2
29 | print(sum)
30 | ```
31 | ---
32 | ### break
33 | 在循环中, [break]() 语句可以提前退出循环。
34 | ```pyhon
35 | n = 1
36 | while n <= 100:
37 | if n > 10: # 当n = 11时,条件满足,执行break语句
38 | break # break语句会结束当前循环
39 | print(n)
40 | n = n + 1
41 | print('END')
42 | ```
43 | ---
44 | ### continue
45 | 在循环过程中,也可以通过 [continue]() 语句,跳过当前的这次循环,直接开始下一次循环。
46 | ```python
47 | n = 0
48 | while n < 10:
49 | n = n + 1
50 | if n % 2 == 0: # 如果n是偶数,执行continue语句
51 | continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
52 | print(n)
53 | ```
54 |
55 |
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/if-else.md:
--------------------------------------------------------------------------------
1 | ### 条件判断
2 | 用 [if]() 语句来实现条件判断:
3 | ```python
4 | age = 20
5 | if age >= 18:
6 | print('your age is',age)
7 | print('adult')
8 | ```
9 | 根据[Python]()的缩进规则,如果 [if]() 语句判断是True,就把缩进的两行print语句执行了,否则,什么也不做。
10 |
11 | 也可以给 [if]() 添加一个 [else]() 语句,意思是,如果 [if]() 判断是False,不要执行 [if]() 的内容,去把 [else]() 执行了:
12 | ```python
13 | age = 3
14 | if age >= 18:
15 | print('your age is', age)
16 | print('adult')
17 | else:
18 | print('your age is', age)
19 | print('teenager')
20 | ```
21 | 注意不要少写了冒号 [:]() 。
22 |
23 | 当然上面的判断是很粗略的,完全可以用[elif]()做更细致的判断:
24 | ```python
25 | age = 3
26 | if age >= 18:
27 | print('adult')
28 | elif age >= 6:
29 | print('teenager')
30 | else:
31 | print('kid')
32 | ```
33 | [if]() 语句执行有个特点,它是从上往下判断,如果在某个判断上是True,把该判断对应的语句执行后,就忽略掉剩下的 [elif]() 和 [else]() ,所以下面的程序打印的是teenager:
34 | ```python
35 | age = 20
36 | if age >= 6:
37 | print('teenager')
38 | elif age >= 18:
39 | print('adult')
40 | else:
41 | print('kid')
42 | ```
43 |
44 |
45 |
--------------------------------------------------------------------------------
/step1-Python-basis/Basic Grammar/list-tuple.md:
--------------------------------------------------------------------------------
1 | ### list
2 | [Python]()内置的一种数据类型是列表:[list]()。[list]()是一种有序的集合,可以随时添加和删除其中的元素。
3 |
4 | 比如,列出班里所有同学的名字,就可以用一个[list]()表示:
5 | ```python
6 | >>> classmates = ['fmw', 'zhang', 'li']
7 | >>> classmates
8 | ['fmw', 'zhang', 'li']
9 | ```
10 | 变量[classmates]()就是一个[list]()。用[len()]()函数可以获得[list]()元素的个数:
11 | ```python
12 | >>> len(classmates)
13 | 3
14 | ```
15 | 用索引来访问list中每一个位置的元素,记得索引下标是从0开始的:
16 | ```python
17 | >>> classmates[0]
18 | 'fmw'
19 | >>> classmates[1]
20 | 'zhang'
21 | >>> classmates[2]
22 | 'li'
23 | >>> classmates[3]
24 | Traceback (most recent call last):
25 | File "", line 1, in
26 | IndexError: list index out of range
27 | ```
28 | 当索引超出了范围时,[Python]()会报一个[IndexError]()错误,所以,要确保索引不要越界,记得最后一个元素的索引是[len(classmates) - 1]()。
29 |
30 | 如果要取最后一个元素,除了计算索引位置外,还可以用 [-1]() 做索引,直接获取最后一个元素:
31 | ```python
32 | >>>classmates[-1]
33 | 'li'
34 | ```
35 | 以此类推,可以获取倒数第2个、倒数第3个:
36 | ```python
37 | >>> classmates[-2]
38 | 'Bob'
39 | >>> classmates[-3]
40 | 'Michael'
41 | >>> classmates[-4]
42 | Traceback (most recent call last):
43 | File "", line 1, in
44 | IndexError: list index out of range
45 | ```
46 | 同样注意不要越界!
47 |
48 | [list]()是一个可变的有序表,所以,可以往[list]()中追加元素到末尾:
49 | ```python
50 | >>> classmates.append('wang')
51 | >>> classmates
52 | ['fmw', 'zhang', 'li', 'wang']
53 | ```
54 | 也可以把元素插入到指定的位置,比如索引号为 [1]() 的位置:
55 | ```python
56 | >>> classmates.insert(1, 'song')
57 | >>> classmates
58 | ['fmw', 'song', 'zhang', 'li', 'wang']
59 | ```
60 | 要删除[list]()末尾的元素,用[pop()]()方法:
61 | ```python
62 | >>> classmates.pop()
63 | 'wang'
64 | >>> classmates
65 | ['fmw', 'song', 'zhang', 'li']
66 | ```
67 | 要删除指定位置的元素,用[pop(i)]()方法,其中 [i]() 是索引位置:
68 | ```python
69 | >>> classmates.pop(1)
70 | 'song'
71 | >>> classmates
72 | ['fmw', 'zhang', 'li']
73 | ```
74 | 要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
75 | ```python
76 | >>> classmates[1] = 'chen'
77 | >>> classmates
78 | ['fmw', 'chen', 'li']
79 | ```
80 | [list]()里面的元素的数据类型也可以不同,比如:
81 | ```python
82 | >>> L = ['Apple', 123, True]
83 | ```
84 | [list]()元素也可以是另一个[list](),比如:
85 | ```python
86 | >>> s = ['python', 'java', ['asp', 'php'], 'scheme']
87 | >>> len(s)
88 | 4
89 | ```
90 | 要注意 [s]() 只有4个元素,其中 [s[2]]() 又是一个[list](),如果拆开写就更容易理解了:
91 | ```python
92 | >>> p = ['asp', 'php']
93 | >>> s = ['python', 'java', p, 'scheme']
94 | ```
95 | 要拿到 ['php']() 可以写 [p[1]]() 或者 [s[2][1]]() ,因此 [s]() 可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。
96 |
97 | 如果一个[list]()中一个元素也没有,就是一个空的[list](),它的长度为0:
98 | ```python
99 | >>> L = []
100 | >>> len(L)
101 | 0
102 | ```
103 | ---
104 | ### tuple
105 | 另一种有序列表叫元组:[tuple]()。[tuple]()和[list]()非常类似,但是[tuple]()一旦初始化就不能修改,比如同样是列出同学的名字:
106 | ```python
107 | >>> classmates = ('fmw', 'zhang', 'li')
108 | ```
109 | 现在,classmates这个[tuple]()不能变了,它也没有[append()](),[insert()]()这样的方法。其他获取元素的方法和[list]()是一样的,你可以正常地使用[classmates[0]](),[classmates[-1]](),但不能赋值成另外的元素。
110 |
111 | 不可变的[tuple]()有什么意义?因为[tuple]()不可变,所以代码更安全。如果可能,能用[tuple]()代替[list]()就尽量用[tuple]()。
112 |
113 | [tuple]()的陷阱:当你定义一个[tuple]()时,在定义的时候,[tuple]()的元素就必须被确定下来,比如:
114 | ```python
115 | >>> t = (1, 2)
116 | >>> t
117 | (1, 2)
118 | ```
119 | 如果要定义一个空的[tuple](),可以写成 [()]() :
120 | ```python
121 | >>> t = ()
122 | >>> t
123 | ()
124 | ```
125 | 但是,要定义一个只有1个元素的[tuple](),如果你这么定义:
126 | ```python
127 | >>> t = (1)
128 | >>> t
129 | 1
130 | ```
131 | 定义的不是[tuple](),是1这个数!这是因为括号()既可以表示[tuple](),又可以表示数学公式中的小括号,这就产生了歧义,因此,[Python]()规定,这种情况下,按小括号进行计算,计算结果自然是1。
132 |
133 | 所以,只有1个元素的[tuple]()定义时必须加一个逗号 [,]() ,来消除歧义:
134 | ```python
135 | >>> t = (1,)
136 | >>> t
137 | (1,)
138 | ```
139 |
--------------------------------------------------------------------------------
/step1-Python-basis/Function/README.md:
--------------------------------------------------------------------------------
1 | # ⚡函数
2 | *这是一个快捷目录栏*
3 | + [调用函数](#调用函数)
4 |
5 | + [定义函数](#定义函数)
6 |
7 | + [函数的参数](#位置参数)
8 |
9 | + [递归函数](#递归函数)
10 |
11 | ---
12 |
13 | # 调用函数
14 | *[Python]()内置了很多有用的函数,我们可以直接调用。*
15 |
16 | 可以在官方函数文档里查我们需要的函数,[https://docs.python.org/3/library/functions.html](https://docs.python.org/3/library/functions.html)
17 |
18 | 也可以在交互式命令行通过[help(abs)]()查看[abs]()函数的帮助信息。
19 |
20 | 调用[abs]()函数:
21 | ```python
22 | >>> abs(100)
23 | 100
24 | >>> abs(-20)
25 | 20
26 | >>> abs(12.34)
27 | 12.34
28 | ```
29 | [max()]() 函数可以接收任意多个参数,并返回最大的那个:
30 | ```python
31 | >>> max(1, 2)
32 | 2
33 | >>> max(2, 3, 1, -5)
34 | 3
35 | ```
36 | ## 数据类型转换
37 | [Python]()内置的常用函数还包括数据类型转换函数,比如 [int()]() 函数可以把其他数据类型转换为整数:
38 | ```python
39 | >>> int('123')
40 | 123
41 | >>> int(12.34)
42 | 12
43 | >>> float('12.34')
44 | 12.34
45 | >>> str(1.23)
46 | '1.23'
47 | >>> str(100)
48 | '100'
49 | >>> bool(1)
50 | True
51 | >>> bool('')
52 | False
53 | ```
54 | 函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
55 | ```python
56 | >>> a = abs # 变量a指向abs函数
57 | >>> a(-1) # 所以也可以通过a调用abs函数
58 | 1
59 | ```
60 |
61 |
62 | [返回目录>>](#函数)
63 |
64 | ---
65 |
66 |
67 | # 定义函数
68 | 在[Python]()中,定义一个函数要使用[def]()语句,依次写出函数名、括号、括号中的参数和冒号[:](),然后,在缩进块中编写函数体,函数的返回值用[return]()语句返回,也可以没有返回,在函数最后自动[return None]()。
69 | ```python
70 | def my_abs(x):
71 | if x >= 0:
72 | return x
73 | else:
74 | return -x
75 | ```
76 | ```python
77 | >>> print(my_abs(-99))
78 | 99
79 | ```
80 | 如果你已经把my_abs()的函数定义保存为a.py文件了,那么,可以在该文件的当前目录下启动Python解释器,用`from a import my_abs`来导入[my_abs()]()函数,注意a是文件名(不含.py扩展名):
81 | ```python
82 | >>> from a import my_abs
83 | >>> my_abs(-9) │
84 | 9
85 | ```
86 | ## 空函数
87 | 如果想定义一个什么事也不做的空函数,可以用 [pass]() 语句:
88 | ```python
89 | def nop():
90 | pass
91 | ```
92 | [pass]() 语句什么都不做,相当于一个占位符。比如现在还没想好怎么写函数的代码,就可以先放一个 [pass](),让代码能运行起来。
93 | ```python
94 | if age >= 18:
95 | pass
96 | ```
97 | 缺少了 [pass](),代码运行就会有语法错误。
98 |
99 | ## 返回多个值
100 | 函数可以返回多个值,比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:
101 | ```python
102 | import math
103 |
104 | def move(x, y, step, angle=0):
105 | nx = x + step * math.cos(angle)
106 | ny = y - step * math.sin(angle)
107 | return nx, ny
108 | ```
109 | > `import math`语句表示导入[math]()包,并允许后续代码引用[math]()包里的[sin]()、[cos]()等函数。
110 |
111 | 然后,我们就可以同时获得返回值:
112 | ```python
113 | >>> x, y = move(100, 100, 60, math.pi / 6)
114 | >>> print(x, y)
115 | 151.96152422706632 70.0
116 | ```
117 | 但其实这只是一种假象,[Python]()函数返回的仍然是单一值:
118 | ```python
119 | >>> r = move(100, 100, 60, math.pi / 6)
120 | >>> print(r)
121 | (151.96152422706632, 70.0)
122 | ```
123 | 其实函数返回值是一个[tuple]()!但是,在语法上,返回一个[tuple]()可以省略括号,而多个变量可以同时接收一个[tuple](),按位置赋给对应的值,所以,[Python]()的函数返回多值其实就是返回一个[tuple](),但写起来更方便。
124 |
125 |
126 | [返回目录>>](#函数)
127 |
128 | ---
129 |
130 |
131 | # 位置参数
132 | 计算 [x²]() 的函数:
133 | ```python
134 | def power(x):
135 | return x * x
136 | ```
137 | 对于[power(x)]()函数,参数x就是一个位置参数。当我们调用[power]()函数时,必须传入有且仅有的一个参数 [x]():
138 | ```python
139 | >>> power(5)
140 | 25
141 | >>> power(15)
142 | 225
143 | ```
144 | 计算 [x]() 的任意 [n]() 次方函数:
145 | ```python
146 | def power(x, n):
147 | s = 1
148 | while n > 0:
149 | n = n - 1
150 | s = s * x
151 | return s
152 | ```
153 | 对于这个修改后的[power(x, n)]()函数,可以计算任意 [n]() 次方:
154 | ```python
155 | >>> power(5, 2)
156 | 25
157 | >>> power(5, 3)
158 | 125
159 | ```
160 | 修改后的[power(x, n)]()函数有两个参数: [x]() 和 [n]() ,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数 [x]() 和 [n]() 。
161 |
162 | ## 默认参数
163 | 新的[power(x, n)]()函数定义没有问题,但是,旧的调用代码失败了,原因是我们增加了一个参数,导致旧的代码因为缺少一个参数而无法正常调用:
164 | ```python
165 | >>> power(5)
166 | Traceback (most recent call last):
167 | File "", line 1, in
168 | TypeError: power() missing 1 required positional argument: 'n'
169 | ```
170 | 这时候,用我们的默认参数。由于我们经常计算 [x²]() ,所以,完全可以把第二个参数 [n]() 的默认值设定为2:
171 | ```python
172 | def power(x, n=2):
173 | s = 1
174 | while n > 0:
175 | n = n - 1
176 | s = s * x
177 | return s
178 | ```
179 | 这样,当我们调用[power(5)]()时,相当于调用[power(5, 2)]():
180 | ```python
181 | >>> power(5)
182 | 25
183 | >>> power(5, 2)
184 | 25
185 | ```
186 | 定义默认参数要牢记一点:默认参数必须指向不变对象,如 [str]() 、[None]() 这样的不变对象。*我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。*
187 |
188 | ## 可变参数
189 | 可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
190 |
191 | 给定一组数字a,b,c……,计算a2 + b2 + c2 + ……
192 |
193 | 由于参数个数不确定,我们首先想到可以把a,b,c……作为一个[list]()或[tuple]()传进来:
194 | ```python
195 | def calc(numbers):
196 | sum = 0
197 | for n in numbers:
198 | sum = sum + n * n
199 | return sum
200 | ```
201 | 但是调用的时候,需要先组装出一个[list]()或[tuple]():
202 | ```python
203 | >>> calc([1, 2, 3])
204 | 14
205 | >>> calc((1, 3, 5, 7))
206 | 84
207 | ```
208 | 如果利用可变参数,调用函数的方式可以简化成这样:
209 | ```python
210 | >>> calc(1, 2, 3)
211 | 14
212 | >>> calc(1, 3, 5, 7)
213 | 84
214 | ```
215 | 所以,我们把函数的参数改为可变参数:
216 | ```python
217 | def calc(*numbers):
218 | sum = 0
219 | for n in numbers:
220 | sum = sum + n * n
221 | return sum
222 | ```
223 | 定义可变参数和定义一个[list]()或[tuple]()参数相比,仅仅在参数前面加了一个 [\*]() 号。在函数内部,参数numbers接收到的是一个[tuple](),因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:
224 | ```python
225 | >>> calc(1, 2)
226 | 5
227 | >>> calc()
228 | 0
229 | ```
230 | 如果已经有一个[list]()或者[tuple](),要调用一个可变参数怎么办?可以这样做:
231 | ```python
232 | >>> nums = [1, 2, 3]
233 | >>> calc(nums[0], nums[1], nums[2])
234 | 14
235 | ```
236 | 这种写法当然是可行的,问题是太繁琐,所以[Python]()允许你在[list]()或[tuple]()前面加一个 [\*]() 号,把[list]()或[tuple]()的元素变成可变参数传进去:
237 | ```python
238 | >>> nums = [1, 2, 3]
239 | >>> calc(*nums)
240 | 14
241 | ```
242 | > `\*nums`表示把`nums`这个[list]()的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
243 |
244 | ## 关键字参数
245 | 可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个[tuple]()。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个[dict]()
246 | ```python
247 | def person(name, age, **kw):
248 | print('name:', name, 'age:', age, 'other:', kw)
249 | ```
250 | 函数[person]()除了必选参数[name]()和[age]()外,还接受关键字参数[kw]()。在调用该函数时,可以只传入必选参数:
251 | ```python
252 | >>> person('Michael', 30)
253 | name: Michael age: 30 other: {}
254 | ```
255 | 也可以传入任意个数的关键字参数:
256 | ```python
257 | >>> person('Bob', 35, city='Beijing')
258 | name: Bob age: 35 other: {'city': 'Beijing'}
259 | >>> person('Adam', 45, gender='M', job='Engineer')
260 | name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
261 | ```
262 | 关键字参数可以扩展函数的功能。如果要做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
263 |
264 | 和可变参数类似,也可以先组装出一个[dict](),然后,把该[dict]()转换为关键字参数传进去:
265 | ```python
266 | >>> extra = {'city': 'Beijing', 'job': 'Engineer'}
267 | >>> person('Jack', 24, city=extra['city'], job=extra['job'])
268 | name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
269 | ```
270 | 当然,上面复杂的调用可以用简化的写法:
271 | ```python
272 | >>> extra = {'city': 'Beijing', 'job': 'Engineer'}
273 | >>> person('Jack', 24, **extra)
274 | name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
275 | ```
276 | `\*\*extra`表示把`extra`这个[dict]()的所有key-value用关键字参数传入到函数的`\*\*kw`参数,`kw`将获得一个[dict](),注意`kw`获得的[dict]()是`extra`的一份拷贝,对`kw`的改动不会影响到函数外的`extra`。
277 |
278 | ## 命名关键字参数
279 | 对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过 [kw]() 检查。
280 |
281 | 仍以[person()]()函数为例,我们希望检查是否有 [city]() 和 [job]() 参数:
282 | ```python
283 | def person(name, age, **kw):
284 | if 'city' in kw:
285 | # 有city参数
286 | pass
287 | if 'job' in kw:
288 | # 有job参数
289 | pass
290 | print('name:', name, 'age:', age, 'other:', kw)
291 | ```
292 | 但是调用者仍可以传入不受限制的关键字参数:
293 | ```python
294 | >>> person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
295 | ```
296 | 如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收 [city]() 和 [job]() 作为关键字参数。这种方式定义的函数如下:
297 | ```python
298 | def person(name, age, *, city, job):
299 | print(name, age, city, job)
300 | ```
301 | 和关键字参数 [\*\*kw]() 不同,命名关键字参数需要一个特殊分隔符 [\*](),[\*]() 后面的参数被视为命名关键字参数:
302 | ```python
303 | >>> person('Jack', 24, city='Beijing', job='Engineer')
304 | Jack 24 Beijing Engineer
305 | ```
306 | 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符 [\*]() 了:
307 | ```python
308 | def person(name, age, *args, city, job):
309 | print(name, age, args, city, job)
310 | ```
311 | 命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:
312 | ```python
313 | >>> person('Jack', 24, 'Beijing', 'Engineer')
314 | Traceback (most recent call last):
315 | File "", line 1, in
316 | TypeError: person() takes 2 positional arguments but 4 were given
317 | ```
318 | 命名关键字参数可以有缺省值,从而简化调用:
319 | ```python
320 | def person(name, age, *, city='Beijing', job):
321 | print(name, age, city, job)
322 | ```
323 | 由于命名关键字参数[city]()具有默认值,调用时,可不传入[city]()参数:
324 | ```python
325 | >>> person('Jack', 24, job='Engineer')
326 | Jack 24 Beijing Engineer
327 | ```
328 | 使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个 [\*]() 作为特殊分隔符。如果缺少 [\*](),[Python]()解释器将无法识别位置参数和命名关键字参数:
329 | ```python
330 | def person(name, age, city, job):
331 | # 缺少 *,city和job被视为位置参数
332 | pass
333 | ```
334 | ## 参数组合
335 | 在[Python]()中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
336 | ```python
337 | def f1(a, b, c=0, *args, **kw):
338 | print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
339 |
340 | def f2(a, b, c=0, *, d, **kw):
341 | print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
342 | ```
343 | 在函数调用的时候,[Python]()解释器自动按照参数位置和参数名把对应的参数传进去。
344 | ```python
345 | >>> f1(1, 2)
346 | a = 1 b = 2 c = 0 args = () kw = {}
347 | >>> f1(1, 2, c=3)
348 | a = 1 b = 2 c = 3 args = () kw = {}
349 | >>> f1(1, 2, 3, 'a', 'b')
350 | a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
351 | >>> f1(1, 2, 3, 'a', 'b', x=99)
352 | a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
353 | >>> f2(1, 2, d=99, ext=None)
354 | a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
355 | ```
356 | 最神奇的是通过一个[tuple]()和[dict](),你也可以调用上述函数:
357 | ```python
358 | >>> args = (1, 2, 3, 4)
359 | >>> kw = {'d': 99, 'x': '#'}
360 | >>> f1(*args, **kw)
361 | a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
362 | >>> args = (1, 2, 3)
363 | >>> kw = {'d': 88, 'x': '#'}
364 | >>> f2(*args, **kw)
365 | a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
366 | ```
367 | 所以,对于任意函数,都可以通过类似`func(*args, **kw)`的形式调用它,无论它的参数是如何定义的。
368 |
369 | > 虽然可以组合多达5种参数,但不要同时使用太多的组合,否则函数接口的可理解性很差。
370 |
371 |
372 | [返回目录>>](#函数)
373 |
374 | ---
375 |
376 |
377 | # 递归函数
378 | 在函数内部,可以调用其他函数。*如果一个函数在内部调用自身本身,这个函数就是递归函数。*
379 |
380 | 计算阶乘`n! = 1 x 2 x 3 x ... x n`,用函数[fact(n)]()表示:
381 | `fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n`
382 | ```python
383 | def fact(n):
384 | if n==1:
385 | return 1
386 | return n * fact(n - 1)
387 | ```
388 | ```python
389 | >>> fact(1)
390 | 1
391 | >>> fact(5)
392 | 120
393 | ```
394 | 递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
395 |
396 | > **注意:** 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈([stack]())这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
397 | ```python
398 | >>> fact(1000)
399 | Traceback (most recent call last):
400 | File "", line 1, in
401 | File "", line 4, in fact
402 | ...
403 | File "", line 4, in fact
404 | RuntimeError: maximum recursion depth exceeded in comparison
405 | ```
406 |
407 |
408 | [返回目录>>](#函数)
409 |
410 | ---
411 |
412 |
--------------------------------------------------------------------------------
/step1-Python-basis/Part-One.md:
--------------------------------------------------------------------------------
1 |
4 |
15 |
16 |
17 |
18 | ## *📑章节目录:*
19 | #### [1. 安装Python环境](#1-安装python环境-1)
20 | [- Windows 操作系统下的安装](#-windows-操作系统下的安装)
21 |
22 | [- 配置 Python 环境变量](#-配置-python-环境变量)
23 |
24 | [- 创建虚拟环境](#-创建虚拟环境)
25 |
26 | [- 虚拟环境的使用及说明](#-虚拟环境的使用及说明 )
27 |
28 | #### [2. 编译器选择](#2-编译器选择-1)
29 | [- 安装 PyCharm 教程](#-安装-pycharm-教程)
30 |
31 | [- 安装 VS Code 教程](#-安装-vs-code-教程)
32 |
33 | #### [3. 写出你的第一个Python程序](#3-写出你的第一个Python程序-1)
34 | [- 执行全局的 Python](#-执行全局的-python)
35 |
36 | [- 执行虚拟环境下的 Python](#-执行虚拟环境下的-python)
37 |
38 | ---
39 |
40 | .
.
.
41 |
42 | ## 1. 安装Python环境
43 |
44 |
45 |
46 | ### ⚡ Windows 操作系统下的安装
47 | ---
48 |
49 | 🐍Python官网下载链接: [https://www.python.org/downloads/](https://www.python.org/downloads/)
50 |
51 | - **Python 版本:** 3.7.2
52 |
53 | - **下载链接地址:** [点击此处开始下载](https://www.python.org/ftp/python/3.7.2/python-3.7.2-amd64.exe)
54 | + 下载完成后双击运行安装程序,如图:
55 |

56 | + 勾选"Add Python 3.7 to PATH"选项后单击"Customize installation"选项。
57 |

58 | + 这里勾选所有选项。其中,
59 | * ["Documentation"](#welcome) 表示安装Python的帮助文档
60 | * ["pip"](#welcome) 表示安装Python的第三方包管理工具
61 | * ["tcl/tk and IDLE"](#welcome) 表示安装Python的集成开发环境
62 | * ["Python test suite"](#welcome) 表示安装Python的标准测试套件
63 | * ["py launcher"](#welcome)和["for all users(requirfes elevation)"](#welcome) 表示允许版本更新
64 |
65 | 👀勾选完所有选项后,单击"Next"
66 | + 保持默认勾选状态,单击"Browse"按钮,选择安装路径,然后点击"Install"开始安装。
67 |

68 |
69 |
70 |
71 |
72 |
73 | ### ⚡ 配置 Python 环境变量
74 | ---
75 |
76 | + 在命令提示框中(cmd):输入 [`path=%path%;C:\Python`](#welcome)
77 |
78 | > **注意:** [`C:\Python`](#welcome) 是 Python 的安装路径
79 |
80 |
81 | #### 🚩[为什么要配置环境变量?](#answer)
82 |
83 | 1. 当安装完成 Python 后,你只能在你的安装目录下(含 [`Python.exe`](#welcome) 可执行文件的目录)来执行 Python.exe 或者引用此路径下的 Python.exe 来执行 Python 程序。
84 | 1. 当在计算机中的其他路径下的执行 Python,会出现报错提示"不是内部或外部命令,也不是可运行的程序或批处理文件。"
85 | 1. 如何在电脑全局中使用 Python,就是我们为何要配置环境变量的原因。
86 |
87 | + 下面介绍一种更常用的配置环境变量的方法:
88 |
89 | * 第一步:鼠标右键"此电脑",选择"属性"
90 |

91 | * 第二步:选择窗口右边"高级系统设置"
92 |

93 | * 第三步:选择"环境变量"
94 |

95 | * 第四步:在系统变量里,双击"Path"以编辑环境变量
96 |

97 | * 第五步:点击右边"新建",输入Python安装路径,完成环境变量配置。
98 |

99 | + 在任意路径处打开CMD窗口,输入`Python`,测试Python是否可以正常运行,输入`exit()`退出运行。
100 |

101 |
102 |
103 |
104 |
105 |
106 | ### ⚡ 创建虚拟环境
107 | ---
108 |
109 | + 在命令提示框(cmd)或任意终端中执行下面指令以安装 [python虚拟环境](#welcome):
110 | ```python
111 | pip install virtualenv
112 | ```
113 |
114 | > **tips:** 可在完成后执行 [`pip list`](#welcome) 来检查是否安装成功,以及执行 [`virtualenv --version`](#welcome) 来查看当前虚拟环境版本。
115 |
116 |
117 |
118 | #### 🚩[为什么要创建虚拟环境?](#answer1)
119 |
120 | 1. 虚拟环境是一个虚拟化,从电脑独立开辟出来的环境。通俗的来讲,虚拟环境就是借助虚拟机docker来把一部分内容独立出来,我们把这部分独立出来的东西称作“容器”,在这个容器中,我们可以只安装我们需要的依赖包,各个容器之间互相隔离,互不影响。[1]
121 | 1. 安装在虚拟环境里的所有包,均不会对环境外的其他包产生影响。反之,在虚拟环境下运行时只能调用虚拟环境中安装的包,不会调用外部的包。
122 | 1. 在很多时候,我们通过 pip 安装的第三方库会有多个版本,而不使用虚拟环境进行隔离,库的版本之间可能会有不兼容情况发生,我们就会遇到无法预期的bug。
123 | 1. 其中 virtualenv 就是创建一个独立的 Python 运行环境(虚拟环境)的工具。
124 |
125 |
126 | + 在安装完 [virtualenv] 后,可在你要创建项目的文件夹下执行:
127 | ```python
128 | virtualenv dir_name
129 | ```
130 |
131 | > **注意:** [`dir_name`](#welcome) 是虚拟环境文件夹名
132 |
133 |
134 | + 比如我这里创建一个文件夹名为 [`partone_env`](#welcome) 的虚拟环境目录:
135 |

136 |
137 | + 我们来看一下这个文件夹下有哪些文件?
138 | ```
139 | Include Lib Scripts tcl
140 | ```
141 | + 暂且不管这些文件都有什么用,但是细心的你也许会发现,这些文件夹在我们安装的 Python 目录下都有,说明我们创建的虚拟环境给我们提供了一个完整的能独立运行 Python 的环境。
142 |
143 | + 除此之外,还有一个 [`pip-selfcheck.json`](#welcome) 文件,它是虚拟环境自我检查的文件,暂不作说明。
144 |
145 | + **说明:** 我们如果用 Python 全局 pip 来安装第三方模块,会安装在 [`C:\Python37\Lib\site-packages`](#welcome) 目录下,但是在虚拟环境下安装,则会安装在 [`partone_env\Lib\site-packages`](#welcome) 目录下。
146 |
147 |
148 |
149 |
150 |
151 | ### ⚡ 虚拟环境的使用及说明
152 | ---
153 |
154 | + 在你创建好的虚拟环境文件夹下,输入 [`s`](#welcome) 字符,按下键盘 [`tab`](#welcome),自动补齐 [`Scripts`](#welcome)(如果没有,请检查是否在当前虚拟环境文件夹下),在 [`Scripts`](#welcome) 后面继续输入反斜杠 [`\`](#welcome),再输入字符 [`a`](#welcome),按下键盘 [`tab`](#welcome) 键自动补齐 [`Scripts\activate`](#welcome),然后回车...
155 | ```
156 | D:\My-Project\partone-env>Scripts\activate
157 | ```
158 |
159 | > **tips:** 虽然多图片方式会让读者更好的完成指示,但是由于 GitHub 网络代理商原因,访问速度会很慢,图片加载也需要很长时间,所以在非特殊时候,我会尽可能少用图片方式。
160 |
161 |
162 | + 完成回车运行后,我们看一下发生了什么情况。在终端路径前面,多了一个 [(partone_env)](#welcome) (名称为虚拟环境名,所以读者可能与我的不同),这表示我们已进入了当前的虚拟环境。然后执行 [`pip list`](#welcome),好干净有没有?
163 | ```
164 | Package Version
165 | ---------- -------
166 | pip 19.0.3
167 | setuptools 41.0.0
168 | wheel 0.33.1
169 | ```
170 |
171 | + 要退出虚拟环境也很简单,同样在虚拟环境文件夹下,输入 [`s`](#welcome) 然后 [`tab`](#welcome),输入反斜杠 [`\`](#welcome) 再加一个 [`d`](#welcome) 然后 [`tab`](#welcome) 。
172 | ```
173 | (partone_env) D:\My-Project\partone_env>Scripts\deactivate.bat
174 | ```
175 |
176 | + 另外,请掌握一个必备的技能 —— 一键导出/入 pip 安装后的包:
177 | + 在虚拟环境根文件夹下将 pip 安装的所有包/模块导入 [`requirements.txt`](#welcome) 文件:
178 | ```
179 | (partone_env) D:\My-Project\partone_env>pip freeze > requirements.txt
180 | ```
181 |
182 | > **tips:** txt 文件前缀可换成任意名,不限定为 requirements,但一般大家都默认为此。注意两点:1. 一定要启用虚拟环境,不然导入的就是全局的 pip 安装过的包。2. 一般都默认在虚拟环境根目录下执行,如果在其他文件夹下执行你在导出时还得去找此 [`requirements.txt`](#welcome) 文件的目录。
183 |
184 |
185 | + 打开 [`requirements.txt`](#welcome) 文件,(如果有内容)我们发现全是我们之前在此虚拟环境下安装过的模块和包。如果没有内容也很正常,说明我们还没在此虚拟环境下安装过第三方模块或包。
186 |
187 | + 那么如何导出这个文件?即 [一键安装这个文件下所有的模块/包](#welcome),很简单,只需要在这个文件对应的目录下执行:
188 | ```python
189 | pip install -r requirements.txt
190 | ```
191 |
192 | + 总言之,虚拟环境是个既简单又极其方便的东西。我们后面会将不同的项目建立在不同的虚拟环境下。
193 |
194 | ---
195 |
196 |
197 |
198 | ## 2. 编译器选择
199 | + Python的实际开发中最常用的是 [PyCharm](#welcome) 这款编译器。它带有一整套可以帮助用户在使用 Python 语言开发时提高其效率的工具,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供了一些高级功能,以用于支持 [Django](#welcome) 框架下的专业 Web 开发。[2]
200 | > 以上关于 PyCharm 的介绍摘自[百度百科](https://baike.baidu.com/)
201 |
202 | + 但是在当前学习阶段我比较推荐的是 [Visual Studio Code](#welcome)(以下简称 VS code)这款微软的跨平台编译器。因为轻便(但是功能强大),这意味着你打开无需过多等待即能用。而且插件安装方便,对于 [Sublime Text](#welcome) 这种轻便好用,语法高亮的文本编辑器来说,插件安装可以说是傻瓜式的(用过Sublime Text 这种编辑器的才能懂它的插件安装的苦)。
203 |
204 | ok,我只介绍这两款软件,下面我会分别给出它们的详细安装教程,以及一些 Python 的相关配置。
205 |
206 |
207 |
208 | ### ⚡ 安装 PyCharm 教程
209 | ---
210 |
211 | + PyCharm安装包笔者已提供,[点击我开始下载 PyCharm5.0.3](https://github.com/fmw666/Python/raw/master/step1-Python-basis/files/pycharm5.0.3.zip)
212 |
213 | + 安装 PyCharm 及汉化详细教程见文档 [PyCharm安装教程.md](https://github.com/fmw666/Python/blob/master/step1-Python-basis/PyCharm%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B.md#-pycharm503-安装详细教程)
214 |
215 |
216 |
217 |
218 |
219 | ### ⚡ 安装 VS Code 教程
220 | ---
221 |
222 | + 安装 VS Code 详细教程见文档 [VS-Code安装教程.md](https://github.com/fmw666/Python/blob/master/step1-Python-basis/VS-Code%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B.md#-vs-code-安装详细教程)
223 |
224 | ---
225 |
226 |
227 |
228 | ## 3. 写出你的第一个Python程序
229 | + 首先,我想说,从这一节到最后所有关于 Python 的基础我都不会着重去讲。打个比方,关于 [print](#welcome) 这个函数就有三个可选参数。如果诸如 [print](#welcome) 函数,其它的函数或者对象方法我也一并全部抛出它们的所有知识点,那么你一定消化不了。或许你是强人,天赋异禀,但相较于平白直抒的抛出知识,我更喜欢寓教于乐的方式。所以一些扩展的语法和知识点我会在 [第二部分——Python 游戏编程](../step2-Pygame) 中去讲述。我觉得学完一个知识点,你能知道它有什么用,为什么会用它,用它能做什么,并且你能实质性的做出什么来,是对你学习记忆最重要的。
230 |
231 | + 这里我选用的编译器是[VS code](#vscode-install)(后面我都会选择用 VS code 来讲解 Python)
232 |
233 |
234 |
235 |
236 |
237 | ### ⚡ 执行全局的 Python
238 | ---
239 |
240 | + 在要存放Python代码的文件夹中右击空白部分,选择"Open with Code"
241 |

242 | + 打开VS code后在左边你的文件夹下,选择"新建文件",然后输入Python文件名(注意添加'.py'后缀)
243 |

244 | + 在建好的Python文件中输入print('Hello World!')
,并按下`ctrl + s`保存文件
245 |

246 | + 在文件内鼠标右击,选择"在终端中运行 Python 文件"
247 |

248 | + 在下方终端中,能看到Python程序执行后的结果
249 |

250 |
251 |
252 |
253 |
254 |
255 | ### ⚡ 执行虚拟环境下的 Python
256 | ---
257 |
258 | + 在**虚拟环境文件夹**下新建文件夹 [`my_code`](#welcome) 用以存放我们的 Python 代码,右击此新创建的文件夹选择"Open with Code"。我们将我们的项目文件夹建在虚拟环境文件夹中,虽然我们的项目文件夹与虚拟环境文件夹不关联,但是我们仍为方便,统一在一个文件夹下进行管理。
259 |

260 | + 打开 VS code 后在建立终端,后续我们均用命令行来操纵,能帮我们熟悉 Linux 指令(VS Code 终端默认是 Linux 的shell)。
261 |

262 | + 然后依次执行如下命令(新建文件夹 → 在此文件夹下创建py文件)
263 |

264 | + 要进入虚拟环境我们使用如下命令:[`$ source ../Scripts/activate`](#welcome)(`/` 为 linux 命令行中目录分隔符,`\` 为 windows 命令行中特有,这里不始用。还有,我们同样按下一个 `s` 再按 `tab` 键智能补齐,以增加速度,显得自己开发技能成熟),然后回车执行,能发现我们已经进入了虚拟环境,如下图:
265 |

266 | + 要退出虚拟环境很简单,在任意路径中,在终端输入 [`deactivate`](#welcome) 然后回车即可~ 这里就不用图片展示了。
267 |
268 |
269 |
270 | ---
271 |
272 | [返回目录⬆](#章节目录)
273 |
274 |
275 |
276 | 第一部分 · 完
277 |
--------------------------------------------------------------------------------
/step1-Python-basis/Part-Three.md:
--------------------------------------------------------------------------------
1 |
4 |
15 |
16 |
17 |
18 | ## *📑章节目录:*
19 | ### [4. Python基本操作](#4)
20 | [- Python 注释](#-python-注释)
21 |
22 | [- Python 的行与缩进](#-python-的行与缩进)
23 |
24 | [- 多行语句](#-多行语句)
25 |
26 | [- Python 输入与输出](#-python-输入与输出)
27 |
28 | [- Python 变量](#-python-变量)
29 |
30 | ### [5. Python数据类型](#5)
31 | [- number (数字)](#-number-数字)
32 |
33 | [- string (字符串)](#-string-字符串)
34 |
35 | [- list (列表)](#-list-列表)
36 |
37 | [- tuple (元组)](#-tuple-元组)
38 |
39 | [- sets (集合)](#-sets-集合)
40 |
41 | [- dictionary (字典)](#-dictionary-字典)
42 |
43 | ---
44 |
45 | .
.
.
46 |
47 | ## 4. Python基本操作
48 |
49 |
50 |
51 | ### ⚡ Python 注释
52 | ---
53 |
54 | xxx
55 |
56 |
57 |
58 |
59 |
60 | ### ⚡ Python 的行与缩进
61 | ---
62 |
63 | xxx
64 |
65 |
66 |
67 |
68 |
69 | ### ⚡ 多行语句
70 | ---
71 |
72 | xxx
73 |
74 |
75 |
76 |
77 |
78 | ### ⚡ Python 输入与输出
79 | ---
80 |
81 | xxx
82 |
83 |
84 |
85 |
86 |
87 | ### ⚡ Python 变量
88 | ---
89 |
90 | xxx
91 |
92 | ---
93 |
94 |
95 |
96 | ## 5. Python数据类型
97 |
98 |
99 |
100 | ### ⚡ number (数字)
101 | ---
102 |
103 | xxx
104 |
105 |
106 |
107 |
108 |
109 | ### ⚡ string (字符串)
110 | ---
111 |
112 | xxx
113 |
114 |
115 |
116 |
117 |
118 | ### ⚡ list (列表)
119 | ---
120 |
121 | xxx
122 |
123 |
124 |
125 |
126 |
127 | ### ⚡ tuple (元组)
128 | ---
129 |
130 | xxx
131 |
132 |
133 |
134 |
135 |
136 | ### ⚡ sets (集合)
137 | ---
138 |
139 | xxx
140 |
141 |
142 |
143 |
144 |
145 | ### ⚡ dictionary (字典)
146 | ---
147 |
148 | xxx
149 |
150 |
151 |
152 | ---
153 |
154 | [返回目录⬆](#章节目录)
155 |
156 |
157 |
158 | 第三部分 · 完
--------------------------------------------------------------------------------
/step1-Python-basis/Part-Two.md:
--------------------------------------------------------------------------------
1 |
4 |
15 |
16 |
17 |
18 | ## *📑章节目录:*
19 | ### [4. Python基本操作](#4)
20 | [- Python 注释](#-python-注释)
21 |
22 | [- Python 的行与缩进](#-python-的行与缩进)
23 |
24 | [- 多行语句](#-多行语句)
25 |
26 | [- Python 输入与输出](#-python-输入与输出)
27 |
28 | [- Python 变量](#-python-变量)
29 |
30 | ### [5. Python数据类型](#5)
31 | [- number (数字)](#-number-数字)
32 |
33 | [- string (字符串)](#-string-字符串)
34 |
35 | [- list (列表)](#-list-列表)
36 |
37 | [- tuple (元组)](#-tuple-元组)
38 |
39 | [- sets (集合)](#-sets-集合)
40 |
41 | [- dictionary (字典)](#-dictionary-字典)
42 |
43 | ---
44 |
45 | .
.
.
46 |
47 | ## 4. Python基本操作
48 |
49 |
50 |
51 | ### ⚡ Python 注释
52 | ---
53 |
54 | + 注释的目的是让人能轻松阅读每一行代码的意义,同时也为程序员后期代码维护提供了方便。在Python中,一共有两种代码注释,一种是 [单行注释](#welcome),另一种是 [多行注释](#welcome)。
55 |
56 | + *单行注释以 `#` 号开头:*
57 | ```python
58 | # 第一个注释
59 | print('Hello World') # 第二个注释
60 | ```
61 |
62 | + *多行注释用两个 `'''` 包含起来:*
63 | ```python
64 | '''
65 | 第一行注释
66 | 第二行注释
67 | '''
68 | print('Hello World') # '''这样不能注释'''
69 | '''这样也能注释'''
70 | ```
71 |
72 |
73 |
74 |
75 |
76 | ### ⚡ Python 的行与缩进
77 | ---
78 |
79 | + Python 最具特色的就是使用缩进来表示代码块,即不需要使用大括号。缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数,缩进不一致会导致代码运行错误。
80 |
81 | + *正确示例:*
82 | ```python
83 | # 同样缩进四个空格
84 | if True:
85 | print('True')
86 | print('Yes')
87 | ```
88 |
89 | + *错误示例:*
90 | ```python
91 | # 缩进四个空格与三个空格,运行会报错
92 | if True:
93 | print('True')
94 | print('Yes')
95 | ```
96 |
97 | + *注意,下面这样的代码由于在不同代码块,所以**不会报错** ,但是我们绝不提倡!*
98 | ```python
99 | if True:
100 | print('True')
101 | else:
102 | print('False')
103 | ```
104 |
105 |
106 |
107 |
108 |
109 | ### ⚡ 多行语句
110 | ---
111 |
112 | + Python 通常是一行写完一条语句,但语句很长的话,可以通过反斜杠'\\'来实现多行语句。
113 | ```python
114 | sentence = "让我们以Python为舟,驶向全栈。这一节讲得是Python基础中的\
115 | 多行语句,我们像这样就实现了写一条长句子的麻烦!"
116 | print(sentence)
117 | ```
118 | > 输出结果为:"让我们以Python为舟,驶向全栈。这一节讲得是Python基础中的多行语句,我们像这样就实现了写一条长句子的麻烦!"
119 |
120 | + 这里有第二种方法,一般来说适合一段长文本的赋值,比如下面这个例子。
121 | ```python
122 | html = """
123 |
124 |
125 | 网页标题
126 |
127 |
128 |
136 |
137 |
138 | """
139 | ```
140 |
141 |
142 |
143 |
144 |
145 |
146 | ### ⚡ Python 输入与输出
147 | ---
148 |
149 | + ***Python 中文编码***
150 |
151 | + 如果在运行[Python](#4.4)程序中,出现以下错误提示:
152 | ```python
153 | SyntaxError: Non-ASCII character '\xe4' in file test.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
154 | ```
155 | + 则未指定编码,需要在文件开头添加 `#coding=utf-8`
156 |
157 | > 对于 [VS code](#vscode-install),可以在界面右下角中选择编码 [UTF-8](#no-jump)
158 |
159 | + ***Python 输出***
160 |
161 | ```python
162 | >>>print('hello,world')
163 | ```
164 | + [print()](#welcome) 函数可以接受多个字符串(字符串用一对`''`或者`""`表示),用逗号`,`或者加号`+`隔开,不过逗号在输出中相当于空格,加号则直接连接:
165 |
166 | ```python
167 | >>>print('hello','world')
168 | hello world
169 | >>>print('hello'+'world')
170 | helloworld
171 | ```
172 | + [print()](#welcome) 函数可以用于打印常数,或作计算
173 |
174 | ```python
175 | >>>print(100)
176 | 100
177 | >>>print(1 + 1.1)
178 | 2.1
179 | ```
180 |
181 | + ***Python 输入***
182 |
183 | ```python
184 | >>>name = input()
185 | fmw
186 | ```
187 | + 当出现[input()](#input)函数以后,命令行会等待用户输入一串字符,此时用户输入的字符串将保留在[name](#no-jump)变量中。
188 |
189 | ```python
190 | >>>name
191 | 'fmw'
192 | >>>print(name)
193 | fmw
194 | ```
195 | + 当然,为了增加用户交互体验,我们可以
196 |
197 | ```python
198 | >>>name = input('Please input your name:')
199 | Please input your name:fmw
200 | >>>print('hello',name)
201 | hello fmw
202 | ```
203 |
204 |
205 |
206 |
207 |
208 | ### ⚡ Python 变量
209 | ---
210 |
211 | + ***变量赋值***
212 |
213 | + Python中的赋值很简单,不需要先指明变量的数据类型。看下面代码:
214 |
215 | ```python
216 | a = 6
217 | print(a)
218 | ```
219 | > **注意:** Python的变量无需提前声明,赋值的同时也就声明了变量。
220 |
221 | + ***变量命名***
222 |
223 | + Python中自带关键字(保留字),变量名不能与之相同。变量名由`字母`、`下划线'_'`和`数字`组成,且不能以数字开头。在Python标准库中提供了一个 [keyword](#no-jump)模块,可以查阅当前版本的所有关键字,方法如下:
224 |
225 | ```python
226 | import keyword
227 | print(keyword.kwlist)
228 | ```
229 |
230 |
231 |
232 | ---
233 |
234 |
235 |
236 | ## 5. Python数据类型
237 |
238 | 🐍Python中有六大数据类型:
239 |
240 |
253 |
254 | > **💡 Python3 中可以使用 [type()](#no-jump) 函数来查看变量数据类型!**
255 |
256 | ```python
257 | # 打印输出变量 variable 的数据类型
258 | print(type(variable))
259 | ```
260 |
261 |
262 |
263 | ### ⚡ number (数字)
264 | ---
265 |
266 | + Python3中支持4种类型的数字:int(整数类型)、float(浮点类型)、bool(布尔类型)、complex(复数类型)
267 |
268 | ```python
269 | var_int = 123
270 | var_float = 1.23
271 | var_bool = True
272 | var_complex = 1+2j
273 |
274 | print(type(var_int))
275 | print(type(var_float))
276 | print(type(var_bool))
277 | print(type(var_complex))
278 | ```
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 | ### ⚡ string (字符串)
287 | ---
288 |
289 | + ***字符串的表示***
290 |
291 | 字符串是单引号、双引号、或者三引号中的内容。其中三引号多用来指示一个[多行字符串](#4.3),在字符串表示中,要注意引号一定要匹配!
292 |
293 | ```python
294 | str1 = 'fmw666'
295 | str2 = "fmw666"
296 | str3 = '''fmw
297 | 666'''
298 | ```
299 |
300 | *值得注意的是,引号内的内容不包含制表符。比如:*
301 |
302 | ```python
303 | >>> print('fmw\n666')
304 | fmw
305 | 666
306 | ```
307 |
308 | *并且如果引号中的字符串出现了同样的引号,会出现报错,应该借用转义符 \\*
309 |
310 | ```python
311 | >>> print('what\'s your name?')
312 | what's your name?
313 | ```
314 |
315 | > [提示:](#no-jump)如果要输入一个反斜杠 \,则需要使用 '\\\\' 的形式来表示。
316 |
317 | *如果引号内字符串的内容不需要转义,只想输出本来的内容,则在字符串前加上 `r` 或` R` 前缀即可,比如:*
318 |
319 | ```python
320 | >>> print(r'fmw\n666')
321 | fmw\n666
322 | ```
323 |
324 | + ***字符串的截取***
325 |
326 | 字符串的截取格式:`[start_index:end_index+1]`,没看懂没关系,下面结合几个例子说明:
327 |
328 | ```python
329 | str = 'fmw666'
330 | str = 'fmw666'
331 | print(str[0]) # 输出的结果为'f'
332 | print(str[-1]) # 输出的结果为'6'
333 | print(str[3:7]) # 输出的结果为'666'
334 | '''更多的留给读者自己思考'''
335 | ```
336 |
337 | + ***强制类型转换***
338 |
339 | 为什么在字符串这里提强制类型转换呢?因为多数时候,我们会用到数字类型向字符类型的转换。尤其在[print()](#print)函数里打印的本质类型就是字符串,包括[input()](#input)函数中读取用户输入后的值为字符串类型。所以我们经常会在以下例子中看到强制类型转换的用处:
340 |
341 | ```python
342 | age = 18
343 | name = '范茂伟'
344 | print(name + '有' + str(age) + '岁')
345 | ```
346 |
347 | 如果不加`str()`则会出现提醒:
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 | ### ⚡ list (列表)
356 | ---
357 |
358 | + Python列表是任意对象的有序集合,列表写在中括号 `[]` 中,元素之间用逗号隔开。这里的任意对象,既可以是列表嵌套列表,也可以是字符串等其他数据类型。
359 |
360 | ```python
361 | >>> list = ['python', 123, [1, 2, 3], 3.14, True]
362 | >>> print(list)
363 | ['python', 123, [1, 2, 3], 3.14, True]
364 | ```
365 |
366 | + 列表的切片和索引和字符串的方法一样:
367 |
368 | ```python
369 | >>> list = ['python', 123, [1, 2, 3], 3.14, True]
370 | >>> print(list[2])
371 | [1, 2, 3]
372 | >>> print(list[1:3])
373 | [123, [1, 2, 3]]
374 | ```
375 |
376 | + 列表内内置很多方法,比如排序[sort()](#no-jump)、倒序[reverse()](#no-jump)等等。(有兴趣和需求自行探索,后续阶段中会再讲解。)
377 |
378 | ```python
379 | >>> list = ['python', 123, [1, 2, 3], 3.14, True]
380 | >>> list.reverse()
381 | >>> print(list)
382 | [True, 3.14, [1, 2, 3], 123, 'python']
383 |
384 | >>> list = [4, 5, 3, 1, 2]
385 | >>> print(list)
386 | [4, 5, 3, 1, 2]
387 | >>> list.sort()
388 | >>> print(list)
389 | [1, 2, 3, 4, 5]
390 | ```
391 |
392 |
393 |
394 |
395 |
396 | ### ⚡ tuple (元组)
397 | ---
398 |
399 | + 元组(tuple)与列表类似,不同之处在于元组内的元素不能修改。元组写在小括号 `()` 中,元素之间用逗号隔开。如下面表示所示:
400 | ```python
401 | >>> tuple = ('python', 123, [1, 2, 3], 3.14, True)
402 | ```
403 |
404 | > 因为元组内的元素不能被修改,所以它自身就不像列表一样存在很多内置方法,但是它的索引和切片依旧和列表一样,这里就不演示了。
405 |
406 | + 元组 [tuple](#welcome) 的陷阱:当你定义一个 [tuple](#welcome) 时,在定义的时候,[tuple](#welcome) 的元素就必须被确定下来,比如:
407 |
408 | ```python
409 | >>> tuple = (1, 2)
410 | >>> tuple
411 | (1, 2)
412 | ```
413 |
414 | 如果要定义一个空的 [tuple](#welcome),可以写成 [()](#no-jump) :
415 |
416 | ```python
417 | >>> tuple = ()
418 | >>> tuple
419 | ()
420 | ```
421 |
422 | 但是,要定义一个只有1个元素的 [tuple](#welcome),如果你这么定义:
423 |
424 | ```python
425 | >>> tuple = (1)
426 | >>> tuple
427 | 1
428 | ```
429 |
430 | 定义的不是 [tuple](#welcome),是1这个数!这是因为括号 () 既可以表示 [tuple](#welcome),又可以表示数学公式中的小括号,这就产生了歧义,因此,[Python](#no-jump) 规定,这种情况下,按小括号进行计算,计算结果自然是1。
431 |
432 | 所以,只有1个元素的 [tuple](#welcome) 定义时必须加一个逗号 '[,](#no-jump)' ,来消除歧义:
433 |
434 | ```python
435 | >>> tuple = (1,)
436 | >>> tuple
437 | (1,)
438 | ```
439 |
440 |
441 |
442 |
443 |
444 | ### ⚡ sets (集合)
445 | ---
446 |
447 | + 集合(set)是一个无序不重复元素的序列,可以用大括号 [{}](#welcome) 或者 [set()](#welcome) 函数来创建。值得注意的是,如果要创建一个空集,必须使用 [set()](#welcome) 函数来创建,而不能使用大括号 [{}](#welcome) ,因为大括号 [{}](#welcome) 是用来创建空字典(dict)的!
448 |
449 | ```python
450 | >>> set = {1, 3, 2, 4, 2, 2}
451 | >>> print(set)
452 | {1, 2, 3, 4}
453 |
454 | >>> a = set()
455 | >>> print(type(a))
456 |
457 | >>> b = {}
458 | >>> print(type(b))
459 |
460 | ```
461 |
462 |
463 |
464 |
465 |
466 | ### ⚡ dictionary (字典)
467 | ---
468 |
469 | + 字典(dict) 是一个无序的键(key)值(value)对的集合,格式如下所示:
470 |
471 | ```python
472 | dict = {key1: value1, key2: value2}
473 | ```
474 |
475 | + 字典的创建方法如下:
476 |
477 | ```python
478 | dict = {
479 | 'name': 'fmw',
480 | 'age': 18
481 | }
482 | print(dict) # 输出:{'name': 'fmw', 'age': 18}
483 | ```
484 |
485 | + 字典添加数据和删除数据:
486 |
487 | ```python
488 | dict = {
489 | 'name': 'fmw',
490 | 'age': 18
491 | }
492 | dict['sex'] = 'boy'
493 | print(dict) # 输出:{'name': 'fmw', 'age': 18, 'sex': 'boy'}
494 |
495 | del dict['age']
496 | print(dict) # 输出:{'name': 'fmw', 'sex': 'boy'}
497 | ```
498 |
499 |
500 |
501 | ---
502 |
503 | [返回目录⬆](#章节目录)
504 |
505 |
506 |
507 | 第二部分 · 完
--------------------------------------------------------------------------------
/step1-Python-basis/PyCharm安装教程.md:
--------------------------------------------------------------------------------
1 |
2 |
⚙ PyCharm5.0.3 安装详细教程
3 |
4 |
5 |
6 | > *tips:因网速原因可能会出现图片加载过慢的情况。*
7 |
8 |
.
9 |
.
10 |
.
11 |
12 | 0. PS:请确保你已经安装了我提供的 [PyCharm5.0.3](https://github.com/fmw666/Python/raw/master/step1-Python-basis/files/pycharm5.0.3.zip) 文件。(若没有,请点击前面文件名开始下载)
13 | 1. 右击软件压缩包选择解压到 pycharm5.0.3\
14 |

15 | 1. 在解压文件夹中找到 pycharm-professional-5.0.3,右击打开
16 |

17 | 1. 点击 Next 按钮
18 |

19 | 1. 点击 Browser 按钮更改安装路径,建议安装到除C盘以外的磁盘,然后单击 Next
20 |

21 | 1. 勾选 Create Desktopshortcut(创建桌面快捷方式),然后点击 Next
22 |

23 | 1. 默认 JetBrains,点击 Install 开始安装
24 |

25 | 1. 等待安装完成
26 |

27 | 1. 点击 Finish 结束(后续工作未完成,先不要勾选 Run PyCharm)
28 |

29 | 1. 在解压文件夹中找到 pycharm5.0.3 汉化包,右击打开
30 |

31 | 1. 选中里面所有的内容,右击复制
32 |

33 | 1. 在你安装 PyCharm5.0.3 的文件夹中找到 lib 文件夹,右击打开
34 |

35 | 1. 选择空白处,右击粘贴
36 |

37 | 1. 在桌面找到 JetBrainsPyCharm5.0.3,右击打开
38 |

39 | 1. 这一步中,勾选 License server,在 License server address:处填入 `http://idea.lanyus.com`,点击确定
40 |

41 |
42 | ---
43 |
44 | 1. 安装完成,后面为配置 wakatime 插件步骤。在下方 `Configure` 中选择'插件'
45 |

46 | 1. 输入 [wakatime](https://wakatime.com/),点击安装
47 |

48 | 1. 在页面中创建新项目,或者打开目录
49 |

50 | 1. 在菜单栏中找到'工具'下方的 `WakaTime Settings`
51 |

52 | 1. 输入 [wakatime](https://wakatime.com/) 官网中你的 API key,点击 'Save'
53 |

54 | 1. 下面开始你愉快的 Python 学习之旅吧~
55 |
--------------------------------------------------------------------------------
/step1-Python-basis/README.md:
--------------------------------------------------------------------------------
1 | # 💬Python 基础
2 | 欢迎来到Python学习的第一大板块—— Python基础学习。要知道,任何一门语言没有前期基础的建立,后期的学习都是不牢固的,所以基础这一部分就显得尤为重要。但是呢,为保证我们能快速进入到后面学习中,在基础这一部分,语法我不会讲得过于深奥,重要的语法扩展我们留到后面的学习中遇到再展开学习。
3 |
4 |
5 |

6 |
7 |
8 | 🏷本章作者推荐阅读文档
9 |
10 | + [Python 官方文档(中文版)](https://learnku.com/docs/tutorial/3.7.0)
11 |
12 | ---
13 |
14 | ### *📑目录索引:*
15 |
16 | > ⭐推荐使用 `ctrl+f` 在网页上查询你想要查找的内容的关键词。
17 |
18 |
19 |
20 |
21 | 一、安装及运行
22 |
23 |
24 |
25 | 二、语法及基本数据类型
26 |
27 |
28 |
29 | 三、函数和类
30 |
31 |
32 |
33 | 四、扩展
34 |
35 | Python 常用模块
36 | Python Web 应用程序
37 | 正则表达式
38 | Python 操纵数据库
39 |
40 |
41 |
42 | ## 第一部分
43 | #### [1. 安装Python环境](Part-One.md#1-安装python环境-1)
44 | [- Windows 操作系统下的安装](Part-One.md#-windows-操作系统下的安装)
45 |
46 | [- 配置 Python 环境变量](Part-One.md#-配置-python-环境变量)
47 |
48 | [- 创建虚拟环境](Part-One.md#-创建虚拟环境)
49 |
50 | [- 虚拟环境的使用及说明](Part-One.md#-虚拟环境的使用及说明 )
51 |
52 | #### [2. 编译器选择](Part-One.md#2-编译器选择-1)
53 | [- 安装 PyCharm 教程](Part-One.md#-安装-pycharm-教程)
54 |
55 | [- 安装 VS Code 教程](Part-One.md#-安装-vs-code-教程)
56 |
57 | #### [3. 写出你的第一个Python程序](Part-One.md#3-写出你的第一个Python程序-1)
58 | [- 执行全局的 Python](Part-One.md#-执行全局的-python)
59 |
60 | [- 执行虚拟环境下的 Python](Part-One.md#-执行虚拟环境下的-python)
61 |
62 | ## 第二部分
63 | #### [4. Python基本操作](#4)
64 | [- Python注释](#4.1)
65 |
66 | [- Python 的行与缩进](#4.2)
67 |
68 | [- 多行语句](#4.3)
69 |
70 | [- Python 输入与输出](#4.4)
71 |
72 | [- Python 变量](#4.5)
73 |
74 | #### [5. Python数据类型](#5)
75 | [- number (数字)](#5.1)
76 |
77 | [- string (字符串)](#5.2)
78 |
79 | [- list (列表)](#5.3)
80 |
81 | [- tuple (元组)](#5.4)
82 |
83 | [- sets (集合)](#5.5)
84 |
85 | [- dictionary (字典)](#5.6)
86 |
87 | ## 第三部分
88 | #### [6. Python语句和函数](#6)
89 | #### [7. Python中的类](#7)
90 |
91 |
92 |
93 |
94 | ---
95 |
96 |
97 |
100 |
--------------------------------------------------------------------------------
/step1-Python-basis/VS-Code安装教程.md:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | > *tips:因网速原因可能会出现图片加载过慢的情况。*
7 |
8 |
.
9 |
.
10 |
.
11 |
12 | 1. 在VS Code官网首页中选择下载对应操作系统的安装包,注意:请选择'Stable'(稳定版)。官网戳这个链接:[https://code.visualstudio.com](https://code.visualstudio.com/)
13 |

14 | 1. 在解压文件夹中找到VSCodeUserSetup-x64-1.30.2.exe,右击打开
15 |

16 | 1. 点击下一步
17 |

18 | 1. 选择'我接受协议',点击下一步
19 |

20 | 1. 点击'游览'更改安装路径,建议安装到除C盘以外的磁盘,然后点击下一步
21 |

22 | 1. 这里选择默认的即可,点击下一步
23 |

24 | 1. 这里建议全选,点击下一步
25 |

26 | 1. 确定无误后点击'安装'
27 |

28 |
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.1.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.10.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.11.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.12.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.13.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.14.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.15.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.16.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.17.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.18.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.19.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.2.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.20.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.21.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.22.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.23.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.24.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.25.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.26.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.27.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.28.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.3.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.4.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.41111.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.41111.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.5.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.6.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.7.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.8.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.9.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs1.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs2.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs3.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs4.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs5.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs6.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs7.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/1.vs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/1.vs8.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.1.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.10.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.11.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.12.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.2.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.3.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.4.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.5.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.6.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.7.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.8.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/2.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/2.9.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/4.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/4.3.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/5.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/5.1.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/5.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/5.2.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/6.0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step1-Python-basis/pics/6.0.png
--------------------------------------------------------------------------------
/step1-Python-basis/pics/readme.md:
--------------------------------------------------------------------------------
1 | 。
2 |
--------------------------------------------------------------------------------
/step2-Pygame/README.md:
--------------------------------------------------------------------------------
1 | # 💬《Python游戏之旅——Pygame》
2 | 我始终觉得游戏是学习编程语言最有效的一种方式,每个人都会想有一款属于自己的游戏。当你学习到一个知识点,你能马上用来当作你游戏开发的一项工具,这无疑是学习的最好的方式。类可以创建一个个对象、循环可以控制游戏进程、判断语句可以控制游戏逻辑、文件可以保存游戏进度……
3 |
4 | ---
5 |
6 | #### *📑快捷目录:*
7 | [1. 初识 Pygame](#1-初识-pygame)
8 |
9 | [2. 打印文本](#2-打印文本)
10 |
11 | [3. 绘制图形](#3-绘制图形)
12 |
13 | [4. 制作pie游戏](#4-制作pie游戏)
14 |
15 | ---
16 |
17 | ## 1. 初识 Pygame
18 | Pygame这个游戏库,能方便我们绘制图形、获取用户输入、执行动画以及使用定时器让游戏按照稳定的帧速率运行。所以,Pygame不仅提供了针对图形和位图的绘制函数,还提供了用于获取用户输入、处理音频播放和监控鼠标和键盘的服务。
19 |
20 | + **Pygame 的安装:**
21 |
22 | 🛠通过Python的第三方包管理工具pip,在终端中执行:
23 | ```python
24 | pip install pygame
25 | ```
26 |
27 |
28 | > 这里我已经安装过这个包,所以出现了如上提醒。
29 | + **Pygame 的使用:**
30 |
31 | ```python
32 | # 使用Pygame的第一步是将Pygame库导入到Python程序中
33 | import pygame
34 | # 下一个步骤是导入Pygame中所有常量,已准备号可以在我们代码中访问它们
35 | from pygame.locals import *
36 | # 使用Pygame库前先对Pygame初始化
37 | pygame.init()
38 | ```
39 | *当执行后上面三条指令后,会出现下面终端中显示的结果:*
40 |

41 | [但是怎么创建一个窗口呢?](#answer)
42 |
43 |
44 | 我们定义一个窗口屏幕的变量`screen`,然后用`pygame.display.set_mode((WIDTH,HEIGHT))`来初始化它
45 | ```python
46 | import pygame
47 | from pygame.locals import *
48 | pygame.init()
49 | # 设置屏幕窗口大小为600×500,宽为600,高为500
50 | screen = pygame.display.set_mode((600,500))
51 | ```
52 | 🐌执行一下看出现了什么结果?屏幕一闪而过。而要解决这个问题我们只需利用一个while循环。
53 | 不仅如此,我们还希望在这个出现的窗口中,我们点击右上角的叉号能关闭程序,所以,我们还需要添加事件处理。
54 | ```python
55 | import pygame
56 | from pygame.locals import *
57 | pygame.init()
58 | screen = pygame.display.set_mode((600,500))
59 | while True:
60 | # 读取事件
61 | for event in pygame.event.get():
62 | # 如果按下右上角叉号
63 | if event.type == QUIT:
64 | # 程序退出
65 | exit()
66 | ```
67 | *运行后的结果:*
68 |

69 |
70 | ---
71 |
72 | [返回目录⬆](#快捷目录)
73 |
74 | ## 2. 打印文本
75 | + **Pygame支持使用`Pygame.font`将文本输出到图形窗口。要绘制文本,我们必须先创建一个字体对象:**
76 |
77 | ```python
78 | myfont = pygame.font.Font(None,60)
79 | ```
80 | > 使用`None`是让pygame使用默认字体,`60`为字体大小。
81 |
82 | + **要说明的是,pygame中打印文本不是一个轻量型的进程,而是一个重量型的进程,所以文本不能快速地绘制到屏幕上,而是渲染到一个平面,然后再将其绘制到屏幕上。由于这是一个极其费时的过程,所以一般来说,建议首先在内存中创建文本平面(或图像),然后再将文本当作一个图像来绘制。**
83 |
84 | ```python
85 | myfont = pygame.font.Font(None,60)
86 | white = 255,255,255
87 | blue = 0,0,255
88 | textImage = myfont.render('Hello Pygame', True, white)
89 | ```
90 | > textImage对象是可以使用`screen.blit()`绘制的平面,我们的高难度的绘制函数,将会在所有的游戏和示例中广泛地使用。`my.font.render()`函数中,第一个参数为文本消息,第二个参数是抗锯齿字体(为了提高质量)的一个标志,第三个参数是颜色(RGB值)
91 |
92 | + **现在我们在之前写好的循环中加入屏幕绘制函数来显示我们的文本:**
93 |
94 | ```python
95 | screen.fill(blue)
96 | screen.blit(textImage, (100,100))
97 | pygame.display.update()
98 | ```
99 |
100 | + **完整代码如下:**
101 |
102 | ```python
103 | import pygame
104 | from pygame.locals import *
105 |
106 | pygame.init()
107 | screen = pygame.display.set_mode((600,500))
108 |
109 | myfont = pygame.font.Font(None,60)
110 | white = 255,255,255
111 | blue = 0,0,255
112 | textImage = myfont.render('Hello Pygame', True, white)
113 | while True:
114 | # 读取事件
115 | for event in pygame.event.get():
116 | # 如果按下右上角叉号
117 | if event.type == QUIT:
118 | # 程序退出
119 | exit()
120 | screen.fill(blue)
121 | screen.blit(textImage, (100,100))
122 | pygame.display.update()
123 | ```
124 |
125 |
126 | ---
127 |
128 | [返回目录⬆](#快捷目录)
129 |
130 | ## 3. 绘制图形
131 | 我们可以使用`pygame.draw`来绘制众多不同的形状。
132 | + **绘制圆**
133 |
134 | *要绘制圆,我们使用`pygame.draw.circle(screen, color, position, radius, width)`,传递的参数为圆的大小、颜色和位置:*
135 |
136 | ```python
137 | import pygame,sys
138 | from pygame.locals import *
139 |
140 | pygame.init()
141 | screen = pygame.display.set_mode((600,500))
142 | pygame.display.set_caption("Drawing Circles")
143 |
144 | while True:
145 | for event in pygame.event.get():
146 | if event.type in (QUIT,KEYDOWN):
147 | sys.exit()
148 |
149 | screen.fill((0,0,200))
150 |
151 | #draw a circle
152 | color = 255,255,0
153 | position = 300,250
154 | radius = 100
155 | width = 10
156 | pygame.draw.circle(screen,color,position,radius,width)
157 |
158 | pygame.display.update()
159 | ```
160 |
161 |
162 | + **绘制矩形**
163 |
164 | *要绘制矩形,我们使用`pygame.draw.rect(screen, color, pos, with)`函数,这里程序中,我们去实现移动矩形,在while循环外我没用`pos_x`和`pos_y`来记录矩形的位置,并创建一对速度变量`vel_x`和`vel_y`:*
165 |
166 | ```python
167 | import pygame
168 | from pygame.locals import *
169 |
170 | pygame.init()
171 | screen = pygame.display.set_mode((600,500))
172 | pygame.display.set_caption("Drawing Rectangles")
173 | pos_x = 300
174 | pos_y = 250
175 | vel_x = 0.2
176 | vel_y = 0.1
177 |
178 | while True:
179 | for event in pygame.event.get():
180 | if event.type == QUIT:
181 | exit()
182 |
183 | screen.fill((0,0,200))
184 |
185 | #move the rectangle
186 | pos_x += vel_x
187 | pos_y += vel_y
188 |
189 | #keep rectangle on the screen
190 | if pos_x > 500 or pos_x < 0:
191 | vel_x = -vel_x
192 | if pos_y > 400 or pos_y < 0:
193 | vel_y = -vel_y
194 |
195 | #draw the rectangle
196 | color = 255,255,0
197 | width = 0 #solid fill
198 | pos = pos_x,pos_y,100,100
199 | pygame.draw.rect(screen,color,pos,width)
200 |
201 | pygame.display.update()
202 | ```
203 |
204 |
205 | + **绘制线条**
206 |
207 | *要绘制线条,我们使用`pygame.draw.line(screen, color, (start_x,start_y), (end_x,end_y), width)`函数:*
208 |
209 | ```python
210 | import pygame
211 | from pygame.locals import *
212 |
213 | pygame.init()
214 | screen = pygame.display.set_mode((600,500))
215 | pygame.display.set_caption("Drawing Lines")
216 |
217 | while True:
218 | for event in pygame.event.get():
219 | if event.type == QUIT:
220 | exit()
221 |
222 | screen.fill((0,80,0))
223 |
224 | #draw the line
225 | color = 100,255,200
226 | width = 8
227 | pygame.draw.line(screen,color,(100,100),(500,400),width)
228 |
229 | pygame.display.update()
230 | ```
231 |
232 |
233 | + **绘制弧形**
234 |
235 | *要绘制弧形,我们使用`pygame.draw.arc(screen,color,position,start_angle,end_angle,width)`函数,其中由于弧形是圆的一部分,所以我们得需要其他函数来表示额外的参数(比如角度):*
236 |
237 | ```python
238 | import pygame
239 | from pygame.locals import *
240 | import math
241 |
242 | pygame.init()
243 | screen = pygame.display.set_mode((600, 500))
244 | pygame.display.set_caption("Drawing Arcs")
245 |
246 | while True:
247 | for event in pygame.event.get():
248 | if event.type == QUIT:
249 | exit()
250 |
251 | screen.fill((0, 0, 200))
252 |
253 | #draw the arc
254 | color = 255,0,255
255 | position = 200,150,200,200
256 | start_angle = math.radians(0)
257 | end_angle = math.radians(180)
258 | width = 8
259 | pygame.draw.arc(screen,color,position,start_angle,end_angle,width)
260 |
261 | pygame.display.update()
262 | ```
263 |
264 |
265 | ---
266 |
267 | [返回目录⬆](#快捷目录)
268 |
269 | ## 4. 制作pie游戏
270 |
271 | ```python
272 | '''
273 | 制作pie游戏,对应四个按键——1,2,3,4
274 | 每当按下一个按键,对应pie区域会改变颜色
275 | 直到按键全部被按下,完成游戏
276 | '''
277 | import pygame
278 | from pygame.locals import *
279 | import math
280 |
281 | pygame.init()
282 | screen = pygame.display.set_mode((600, 500))
283 | pygame.display.set_caption("The Pie Game - Press 1,2,3,4")
284 | myfont = pygame.font.Font(None, 60)
285 |
286 | color = 200, 80, 60
287 | width = 4
288 | x = 300
289 | y = 250
290 | radius = 200
291 | position = x-radius, y-radius, radius*2, radius*2
292 |
293 | piece1 = False
294 | piece2 = False
295 | piece3 = False
296 | piece4 = False
297 |
298 | while True:
299 | for event in pygame.event.get():
300 | if event.type == QUIT:
301 | exit()
302 | elif event.type == KEYUP:
303 | if event.key == K_ESCAPE:
304 | exit()
305 | elif event.key == K_KP1:
306 | piece1 = True
307 | elif event.key == K_KP2:
308 | piece2 = True
309 | elif event.key == K_KP3:
310 | piece3 = True
311 | elif event.key == K_KP4:
312 | piece4 = True
313 |
314 | # 屏幕绘制
315 | screen.fill((0, 0, 200))
316 |
317 | # 绘制数字
318 | textImg1 = myfont.render('1', True, color)
319 | screen.blit(textImg1, (x+radius/2-20, y-radius/2))
320 | textImg2 = myfont.render('2', True, color)
321 | screen.blit(textImg2, (x-radius/2, y-radius/2))
322 | textImg3 = myfont.render('3', True, color)
323 | screen.blit(textImg3, (x-radius/2, y+radius/2-20))
324 | textImg4 = myfont.render('4', True, color)
325 | screen.blit(textImg4, (x+radius/2-20, y+radius/2-20))
326 |
327 | # 绘制 piece
328 | if piece1:
329 | start_angle = math.radians(0)
330 | end_angle = math.radians(90)
331 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
332 | pygame.draw.line(screen, color, (x, y), (x, y-radius), width)
333 | pygame.draw.line(screen, color, (x, y), (x+radius, y), width)
334 | if piece2:
335 | start_angle = math.radians(90)
336 | end_angle = math.radians(180)
337 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
338 | pygame.draw.line(screen, color, (x, y), (x, y-radius), width)
339 | pygame.draw.line(screen, color, (x, y), (x-radius, y), width)
340 | if piece3:
341 | start_angle = math.radians(180)
342 | end_angle = math.radians(270)
343 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
344 | pygame.draw.line(screen, color, (x, y), (x-radius, y), width)
345 | pygame.draw.line(screen, color, (x, y), (x, y+radius), width)
346 | if piece4:
347 | start_angle = math.radians(270)
348 | end_angle = math.radians(360)
349 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
350 | pygame.draw.line(screen, color, (x, y), (x, y+radius), width)
351 | pygame.draw.line(screen, color, (x, y), (x+radius, y), width)
352 |
353 | # 完成按键任务
354 | if piece1 and piece2 and piece3 and piece4:
355 | color = 0, 255, 0
356 |
357 | pygame.display.update()
358 | ```
359 |
360 |
361 | ---
362 |
363 | [返回目录⬆](#快捷目录)
364 |
365 | ---
366 |
367 |
368 |
371 |
372 |
--------------------------------------------------------------------------------
/step2-Pygame/files/README.md:
--------------------------------------------------------------------------------
1 | 这里面有本章示例的demo还有一些作者其他的文件
2 |
--------------------------------------------------------------------------------
/step2-Pygame/files/pie游戏.py:
--------------------------------------------------------------------------------
1 | '''
2 | 制作pie游戏,对应四个按键——1,2,3,4
3 | 每当按下一个按键,对应pie区域会改变颜色
4 | 直到按键全部被按下,完成游戏
5 | '''
6 | import pygame
7 | from pygame.locals import *
8 | import math
9 |
10 | pygame.init()
11 | screen = pygame.display.set_mode((600, 500))
12 | pygame.display.set_caption("The Pie Game - Press 1,2,3,4")
13 | myfont = pygame.font.Font(None, 60)
14 |
15 | color = 200, 80, 60
16 | width = 4
17 | x = 300
18 | y = 250
19 | radius = 200
20 | position = x-radius, y-radius, radius*2, radius*2
21 |
22 | piece1 = False
23 | piece2 = False
24 | piece3 = False
25 | piece4 = False
26 |
27 | while True:
28 | for event in pygame.event.get():
29 | if event.type == QUIT:
30 | exit()
31 | elif event.type == KEYUP:
32 | if event.key == K_ESCAPE:
33 | exit()
34 | elif event.key == K_KP1:
35 | piece1 = True
36 | elif event.key == K_KP2:
37 | piece2 = True
38 | elif event.key == K_KP3:
39 | piece3 = True
40 | elif event.key == K_KP4:
41 | piece4 = True
42 |
43 | # 屏幕绘制
44 | screen.fill((0, 0, 200))
45 |
46 | # 绘制数字
47 | textImg1 = myfont.render('1', True, color)
48 | screen.blit(textImg1, (x+radius/2-20, y-radius/2))
49 | textImg2 = myfont.render('2', True, color)
50 | screen.blit(textImg2, (x-radius/2, y-radius/2))
51 | textImg3 = myfont.render('3', True, color)
52 | screen.blit(textImg3, (x-radius/2, y+radius/2-20))
53 | textImg4 = myfont.render('4', True, color)
54 | screen.blit(textImg4, (x+radius/2-20, y+radius/2-20))
55 |
56 | # 绘制 piece
57 | if piece1:
58 | start_angle = math.radians(0)
59 | end_angle = math.radians(90)
60 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
61 | pygame.draw.line(screen, color, (x, y), (x, y-radius), width)
62 | pygame.draw.line(screen, color, (x, y), (x+radius, y), width)
63 | if piece2:
64 | start_angle = math.radians(90)
65 | end_angle = math.radians(180)
66 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
67 | pygame.draw.line(screen, color, (x, y), (x, y-radius), width)
68 | pygame.draw.line(screen, color, (x, y), (x-radius, y), width)
69 | if piece3:
70 | start_angle = math.radians(180)
71 | end_angle = math.radians(270)
72 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
73 | pygame.draw.line(screen, color, (x, y), (x-radius, y), width)
74 | pygame.draw.line(screen, color, (x, y), (x, y+radius), width)
75 | if piece4:
76 | start_angle = math.radians(270)
77 | end_angle = math.radians(360)
78 | pygame.draw.arc(screen, color, position, start_angle, end_angle, width)
79 | pygame.draw.line(screen, color, (x, y), (x, y+radius), width)
80 | pygame.draw.line(screen, color, (x, y), (x+radius, y), width)
81 |
82 | # 完成按键任务
83 | if piece1 and piece2 and piece3 and piece4:
84 | color = 0, 255, 0
85 |
86 | pygame.display.update()
87 |
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.1.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.2.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.3.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.4.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.5.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.6.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.6.gif
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.7.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.8.png
--------------------------------------------------------------------------------
/step2-Pygame/pics/1.9.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step2-Pygame/pics/1.9.gif
--------------------------------------------------------------------------------
/step2-Pygame/pics/readme.md:
--------------------------------------------------------------------------------
1 | 图片资源文件夹
2 |
--------------------------------------------------------------------------------
/step3-PyQt5-GUI/README.md:
--------------------------------------------------------------------------------
1 | # 💬《Python之 GUI 编程——PyQt5》
2 |
3 | 图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。我们利用 GUI 编程可以写出很多实用的桌面应用程序,这样可以使我们更多的 python 函数和脚本更好的封装起来以此来方便用户的使用。
4 |
5 | > ⭐ python 的图形界面库有很多,常用的有 [Tkinter](#welcome)、[PyQt](#welcome)、[wxPython](#welcome)、[PyGTK](#welcome)、[PySide](#welcome)。
6 | >> 我们这里采用的是跨平台的 GUI 工具,Qt 所有类的 Python 封装 PyQt5 这个库。
7 |
8 | ---
9 |
10 | 🏷PyQt5 学习参考网站
11 | + [PyQt5 中文教程](https://maicss.gitbooks.io/pyqt5/content/)
12 |
13 | - [项目 github 地址](https://github.com/maicss/PyQt5-Chinese-tutorial)
14 |
15 | + [PyQt 官方网站](https://riverbankcomputing.com/news)
16 |
17 | ## 目录
18 | [1. 初识和使用窗口](#1-初识和使用窗口)
19 |
20 | [2. 控件](#2-控件)
21 |
22 | [3. 布局管理](#3-布局管理)
23 |
24 | [4. 事件和信号](#4-事件和信号)
25 |
26 | [5. 使用 QSS 来美化界面](#5-使用-qss-来美化界面)
27 |
28 | [6. 将 pyqt5 程序打包为 exe 可执行文件](#6-将-pyqt5-程序打包为-exe-可执行文件)
29 |
30 | ---
31 |
32 | ## 1. 初识和使用窗口
33 |
34 | + 下载依赖模块
35 |
36 | ```python
37 | pip install pyqt5
38 | ```
39 |
40 | + 简单的窗口
41 |
42 | ```python
43 | # 这里引入了PyQt5.QtWidgets模块,这个模块包含了基本的组件。
44 | import sys
45 | from PyQt5.QtWidgets import QApplication, QWidget
46 |
47 | if __name__ == '__main__':
48 | # 每个PyQt5应用都必须创建一个应用对象。
49 | # sys.argv是一组命令行参数的列表。
50 | # Python可以在shell里运行,这个参数提供对脚本控制的功能。
51 | app = QApplication(sys.argv)
52 |
53 | # QWidge控件是一个用户界面的基本控件,它提供了基本的应用构造器。
54 | w = QWidget()
55 | # resize()方法能改变控件的大小,这里的意思是窗口宽250px,高150px。
56 | w.resize(250, 150)
57 | # move()是修改控件位置的的方法,它把控件放置到屏幕坐标的(300, 300)的位置。
58 | # 注:屏幕坐标系的原点是屏幕的左上角。
59 | w.move(300, 300)
60 | # 我们给这个窗口添加了一个标题,标题在标题栏展示。
61 | w.setWindowTitle('Simple')
62 | # show()能让控件在桌面上显示出来。
63 | w.show()
64 |
65 | # 主循环从窗口上接收事件,并把事件传入到派发到应用控件里。
66 | # 当调用exit()方法或直接销毁主控件时,主循环就会结束。
67 | # sys.exit()方法能确保主循环安全退出,外部环境能通知主控件怎么结束。
68 | # exec_()之所以有个下划线,是因为exec是一个Python的关键字。
69 | sys.exit(app.exec_())
70 | ```
71 |
72 | + 我们一般把窗体信息封装成一个类,比如这样:
73 |
74 | ```python
75 | import sys
76 | from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication
77 |
78 |
79 | class Example(QWidget):
80 |
81 | def __init__(self):
82 | super().__init__()
83 |
84 | self.initUI()
85 |
86 |
87 | def initUI(self):
88 |
89 | self.resize(250, 150)
90 | self.center()
91 |
92 | self.setWindowTitle('Center')
93 | self.show()
94 |
95 | # 后面可以再初始化一些控件(控件见下一节)
96 |
97 |
98 | def center(self):
99 |
100 | qr = self.frameGeometry()
101 | cp = QDesktopWidget().availableGeometry().center()
102 | qr.moveCenter(cp)
103 | self.move(qr.topLeft())
104 |
105 |
106 | if __name__ == '__main__':
107 |
108 | app = QApplication(sys.argv)
109 | ex = Example()
110 | sys.exit(app.exec_())
111 | ```
112 |
113 | > center() 方法是将窗体居中于屏幕。
114 |
115 |
118 |
119 | ## 2. 控件
120 |
121 | + 标签类:`QLabel`
122 |
123 | + 文本框类:`QLineEdit`、`QTextEdit`
124 |
125 | + 按钮类:`QPushButton`、`QRadioButton`、`QCheckBox`
126 |
127 | + 下拉列表框:`QComboBox`
128 |
129 | + 计数器:`QSpinBox`
130 |
131 | + 滑动条:`QSlider`
132 |
133 | + 窗口绘图类:`QPainter`、`QPen`、`QBrush`、`QPixmap`
134 |
135 | + 拖曳与剪贴板:`DragEnterEvent`、`DropEvent`、`QClipboard`
136 |
137 | + 日历控件:`QCalendar`
138 |
139 | + 日期时间控件:`QDateTimeEdit`
140 |
141 | + 菜单栏:`QMenuBar`
142 |
143 | + 工具栏:`QToolBar`
144 |
145 | + 状态栏:`QStatusBar`
146 |
147 | + 消息弹出式对话框:`QMessageBox`
148 |
149 | + 输入对话框:`QInputDialog`
150 |
151 | + 字体选择对话框:`QFontDialog`
152 |
153 | + 打开保存文件对话框:`QFileDialog`
154 |
155 |
158 |
159 | ## 3. 布局管理
160 |
161 | + 盒布局(强适应性)
162 |
163 | ```python
164 | import sys
165 | from PyQt5.QtWidgets import (QWidget, QPushButton,
166 | QHBoxLayout, QVBoxLayout, QApplication)
167 |
168 |
169 | class Example(QWidget):
170 |
171 | def __init__(self):
172 | super().__init__()
173 |
174 | self.initUI()
175 |
176 |
177 | def initUI(self):
178 |
179 | okButton = QPushButton("OK")
180 | cancelButton = QPushButton("Cancel")
181 |
182 | hbox = QHBoxLayout()
183 | hbox.addStretch(1)
184 | hbox.addWidget(okButton)
185 | hbox.addWidget(cancelButton)
186 |
187 | vbox = QVBoxLayout()
188 | vbox.addStretch(1)
189 | vbox.addLayout(hbox)
190 |
191 | self.setLayout(vbox)
192 |
193 | self.setGeometry(300, 300, 300, 150)
194 | self.setWindowTitle('Buttons')
195 | self.show()
196 |
197 |
198 | if __name__ == '__main__':
199 |
200 | app = QApplication(sys.argv)
201 | ex = Example()
202 | sys.exit(app.exec_())
203 | ```
204 |
205 | + 栅格布局(最常用)
206 |
207 | ```python
208 | import sys
209 | from PyQt5.QtWidgets import (QWidget, QGridLayout,
210 | QPushButton, QApplication)
211 |
212 |
213 | class Example(QWidget):
214 |
215 | def __init__(self):
216 | super().__init__()
217 |
218 | self.initUI()
219 |
220 |
221 | def initUI(self):
222 |
223 | grid = QGridLayout()
224 | self.setLayout(grid)
225 |
226 | names = ['Cls', 'Bck', '', 'Close',
227 | '7', '8', '9', '/',
228 | '4', '5', '6', '*',
229 | '1', '2', '3', '-',
230 | '0', '.', '=', '+']
231 |
232 | positions = [(i,j) for i in range(5) for j in range(4)]
233 |
234 | for position, name in zip(positions, names):
235 |
236 | if name == '':
237 | continue
238 | button = QPushButton(name)
239 | grid.addWidget(button, *position)
240 |
241 | self.move(300, 150)
242 | self.setWindowTitle('Calculator')
243 | self.show()
244 |
245 |
246 | if __name__ == '__main__':
247 |
248 | app = QApplication(sys.argv)
249 | ex = Example()
250 | sys.exit(app.exec_())
251 | ```
252 |
253 |
256 |
257 | ## 4. 事件和信号
258 |
259 | ```python
260 | import sys
261 | from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication
262 |
263 |
264 | class Example(QMainWindow):
265 |
266 | def __init__(self):
267 | super().__init__()
268 |
269 | self.initUI()
270 |
271 |
272 | def initUI(self):
273 |
274 | btn1 = QPushButton("Button 1", self)
275 | btn1.move(30, 50)
276 |
277 | btn2 = QPushButton("Button 2", self)
278 | btn2.move(150, 50)
279 |
280 | btn1.clicked.connect(self.buttonClicked)
281 | btn2.clicked.connect(self.buttonClicked)
282 |
283 | self.statusBar()
284 |
285 | self.setGeometry(300, 300, 290, 150)
286 | self.setWindowTitle('Event sender')
287 | self.show()
288 |
289 |
290 | def buttonClicked(self):
291 |
292 | sender = self.sender()
293 | self.statusBar().showMessage(sender.text() + ' was pressed')
294 |
295 |
296 | if __name__ == '__main__':
297 |
298 | app = QApplication(sys.argv)
299 | ex = Example()
300 | sys.exit(app.exec_())
301 | ```
302 |
303 |
306 |
307 | ## 5. 使用 QSS 来美化界面
308 |
309 | > 参考文章:[pyqt5中样式的介绍](https://blog.csdn.net/kuangshp128/article/details/87089446)
310 |
311 |
314 |
315 | ## 6. 将 pyqt5 程序打包为 exe 可执行文件
316 |
317 | + 使用的打包工具是 pyinstaller
318 |
319 | ```python
320 | pip install pyinstaller
321 | ```
322 |
323 | + 执行指令
324 |
325 | ```python
326 | pyinstaller -Fw -i favicon xxx.py
327 | ```
328 |
329 | > -F:表示生成单个可执行文件;-w:表示去掉控制台窗口;-i:表示增添 icon 图标
330 |
331 |
334 |
335 | ---
336 |
337 |
338 |
--------------------------------------------------------------------------------
/step4-Algorithm/Discrete-Mathematics/README.md:
--------------------------------------------------------------------------------
1 | # 离散数学
2 |
--------------------------------------------------------------------------------
/step4-Algorithm/README.md:
--------------------------------------------------------------------------------
1 | # 💬《Python 数据结构与算法》
2 | 我认为在计算机编程学习中,最为重要的就是数据结构与算法这门课程。这门课的学习会使你整个编程生涯终身受用,我这里可绝对不是夸大其词,在面试中,看似面试官问的是相关语言,其实问的是语言背后的数据结构,看似问的是数据结构,其实问的是背后实现的算法。需要注意的是,我们专门有一个 repo 是对数据结构和算法这两门课程的深度讲解,在那篇文档中,我主要是基于 C或C++ 。所以关于数据结构和算法的基础知识和深度讲解请转至上述 repo,链接请戳 [这里](https://github.com/fmw666/Data-Structure/)。本文主要基于 Python 实现大部分数据结构与算法。
3 |
4 | ---
5 |
6 |
7 |

8 |
9 |
10 | #### *⭐ 本章作者呕心沥血推荐读物*
11 |
12 | + [《离散数学(第五版)》](https://www.baidu.com/link?url=4svn2zwEsw5PWP8ZJPr9WYONIA6nIvY5Ocoz_1Aa7VE6k4bjanu-_wmeI4RQAayZTdR_Mb7h8t-NVKhTixUvkshzzuMjtTVZc1adl8h0hnW&wd=&eqid=dd79a6f80008cecb000000035cdaaf08)- 清华大学出版社
13 |
14 | + [Python3.7 官方中文教程之数据结构](https://docs.python.org/zh-cn/3/tutorial/datastructures.html)
15 |
16 | + [《数据结构与算法:Python语言描述》](https://book.douban.com/subject/26702568/)
17 |
18 | + [《算法图解》](https://book.douban.com/subject/26979890/)- 人民邮电出版社
19 |
20 | ## 第一部分
21 |
22 | [asd](#)
23 |
--------------------------------------------------------------------------------
/step4-Algorithm/code/Dijkstra之解决图中任意两点间最短距离.py:
--------------------------------------------------------------------------------
1 | # 定义一个无穷大值
2 | INF = 9999
3 | # 图的顶点起始索引值
4 | START_INDEX = 0
5 | # 文件保存信息--字符串
6 | OUTPUT_STR = ''
7 |
8 | # 矩阵类,存储邻接矩阵有效信息
9 | # category='0'代表无向图、='1'代表有向图
10 | class Matrix(object):
11 |
12 | def __init__(self, vexnum, edge, category):
13 | self.vexnum = vexnum
14 | self.edge = edge
15 | self.category = category
16 |
17 | def create_matrix(self):
18 | self.mgraph = [[INF]*vexnum for i in range(vexnum)]
19 | print('==请依次输入每条边两个顶点以及其权重==')
20 | print('(如:v' + str(START_INDEX) \
21 | + '->v' + str(START_INDEX + 1) \
22 | + ' : 2,则依次输入:' + str(START_INDEX) \
23 | + ' ' + str(START_INDEX + 1) + ' 2)')
24 | count = 1
25 | while count <= self.edge:
26 | if count == 1:
27 | print('---')
28 | start = int(input('第' + str(count) + '条边第一个顶点:'))
29 | end = int(input('第' + str(count) + '条边第二个顶点:'))
30 | weight = int(input('第' + str(count) + '条边第权重:'))
31 | print('---')
32 | self.mgraph[start-START_INDEX][end-START_INDEX] = weight
33 | # 无向图情况
34 | if self.category == '0':
35 | self.mgraph[end-START_INDEX][start-START_INDEX] = weight
36 | count += 1
37 |
38 | def print_matrix(self):
39 | global OUTPUT_STR
40 | print('\n==图的邻接矩阵==')
41 | OUTPUT_STR = OUTPUT_STR + '==图的邻接矩阵==\n'
42 | # 行数
43 | for row in range(self.vexnum):
44 | # 列数
45 | for col in range(self.vexnum):
46 | if self.mgraph[row][col] == INF and row != col:
47 | print('∞ ',end='')
48 | OUTPUT_STR = OUTPUT_STR + '∞ '
49 | elif row == col:
50 | print('0 ',end='')
51 | OUTPUT_STR = OUTPUT_STR + '0 '
52 | else:
53 | print(str(self.mgraph[row][col]) + ' ', end='')
54 | OUTPUT_STR = OUTPUT_STR + str(self.mgraph[row][col]) + ' '
55 | print('')
56 | OUTPUT_STR = OUTPUT_STR + '\n'
57 |
58 | def print_shortest_dis(self):
59 | global OUTPUT_STR
60 | for v in range(self.vexnum):
61 | self.info = []
62 | PATH, VALUE, VISIT = 0, 1, 2
63 | # 从第一个顶点开始到最后一个顶点结束
64 | for vex in range(self.vexnum):
65 | # 设置当前路径信息
66 | path = 'v' + str(v + START_INDEX) + ' -> v' + str(vex + START_INDEX)
67 | value = self.mgraph[v][vex]
68 | visit = False
69 | self.info.append([path, value, visit])
70 | # 找到自己点
71 | self.info[v][VISIT] = True
72 |
73 | count = 1
74 | # 计算剩余顶点的最短路径
75 | while count != self.vexnum:
76 | # temp 保存 info 数组中最小的下标
77 | # minv 记录当前的最小值
78 | temp = 0
79 | minv = INF
80 | for i in range(self.vexnum):
81 | if not self.info[i][VISIT] and self.info[i][VALUE] < minv:
82 | minv = self.info[i][VALUE]
83 | temp = i
84 | self.info[temp][VISIT] = True
85 | count += 1
86 | for i in range(self.vexnum):
87 | if not self.info[i][VISIT] and self.mgraph[temp][i] != INF and (self.info[temp][VALUE] + self.mgraph[temp][i]) < self.info[i][VALUE]:
88 | self.info[i][VALUE] = self.info[temp][VALUE] + self.mgraph[temp][i]
89 | self.info[i][PATH] = self.info[temp][PATH] + ' -> v' + str(i + 1)
90 | print('\n==以 v' + str(v + START_INDEX) + ' 为起点到任意点的最短路径==')
91 | OUTPUT_STR = OUTPUT_STR + '\n==以 v' + str(v + START_INDEX) + ' 为起点到任意点的最短路径==\n'
92 | for idx in range(self.vexnum):
93 | if self.info[idx][VALUE] != INF:
94 | print(self.info[idx][PATH] + ' = ' + str(self.info[idx][VALUE]))
95 | OUTPUT_STR = OUTPUT_STR + \
96 | self.info[idx][PATH] + ' = ' + \
97 | str(self.info[idx][VALUE]) + '\n'
98 | else:
99 | print(self.info[idx][PATH] + ' 不存在最短路径')
100 | OUTPUT_STR = OUTPUT_STR + \
101 | self.info[idx][PATH] + ' 不存在最短路径\n'
102 |
103 | def save_result(self, filename):
104 | with open(filename + '.txt', 'w', encoding='utf-8') as fp:
105 | fp.write(OUTPUT_STR)
106 | fp.close()
107 |
108 | def checkve(vexnum, edge):
109 | if vexnum <=0 \
110 | or edge <=0 \
111 | or ((vexnum*(vexnum-1))/2) < edge:
112 | return False
113 | return True
114 |
115 | if __name__ == "__main__":
116 | '''
117 | 输入参数:图的相关信息 (顶点数、边数、图的类型)
118 | 顶点个数 i 生成顶点为:v0、v1……vi-1(即顶点下标默认从0开始)
119 | 边与顶点个数关系:((vexnum*(vexnum - 1)) / 2) < edge
120 |
121 | 输出结果:邻接矩阵、vi 到除自己点以外任意点的最短距离
122 | (即任意两点间的最短距离)
123 |
124 | 作者:fmw666 (github 用户名)
125 | 代码开源于:https://github.com/fmw666/
126 | '''
127 | print('==请输入相关图信息==')
128 | vexnum = int(input('顶点个数:'))
129 | edge = int(input('边的条数:'))
130 | while not checkve(vexnum, edge):
131 | print('输入点/边信息有误,请重新输入!')
132 | vexnum = int(input('顶点个数:'))
133 | edge = int(input('边的条数:'))
134 | ans = input('请确认图的类型:0.无向图 1.有向图\n输入序号:')
135 | print('\n==请自定义你的顶点下标起始索引==')
136 | START_INDEX = int(input('(推荐起始索引为 0 或 1):'))
137 | OUTPUT_STR = OUTPUT_STR + '==图的相关信息==\n顶点个数:' + str(vexnum)\
138 | + '\n边的条数:' + str(edge) + '\n图的类型:'
139 | if ans == '0' or ans == '1' and START_INDEX > 0:
140 | print('\n==请确认输入信息==\n顶点个数:' + str(vexnum)\
141 | + '\n边的条数:' + str(edge))
142 | if ans == '0':
143 | print('图的类型:无向图')
144 | OUTPUT_STR = OUTPUT_STR + '无向图\n'
145 | elif ans == '1':
146 | print('图的类型:有向图')
147 | OUTPUT_STR = OUTPUT_STR + '有向图\n'
148 | print('起始索引:v' + str(START_INDEX) + '\n')
149 | OUTPUT_STR = OUTPUT_STR + '起始索引:v' + str(START_INDEX) + '\n\n'
150 | else:
151 | print('输入有误,请从给出序号中进行选择!')
152 |
153 | matrix = Matrix(vexnum, edge, ans)
154 |
155 | matrix.create_matrix()
156 | matrix.print_matrix()
157 | matrix.print_shortest_dis()
158 | ifsave = input('\n\n==是否保存当前结果到当前文件夹下?==\n(0.否 1.是):')
159 | if ifsave == '1':
160 | filename = input('\n请输入文件名(默认扩展名为.txt):')
161 | matrix.save_result(filename)
162 | print('保存成功!程序已运行完成,请在当前目录下查看查看保存文件。')
163 |
--------------------------------------------------------------------------------
/step4-Algorithm/code/input.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step4-Algorithm/code/input.jpg
--------------------------------------------------------------------------------
/step4-Algorithm/pics/README.md:
--------------------------------------------------------------------------------
1 | # 图片管理
2 |
--------------------------------------------------------------------------------
/step4-Algorithm/pics/binarytree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step4-Algorithm/pics/binarytree.jpg
--------------------------------------------------------------------------------
/step5-Python-web/Django/Django-Ubuntu-BlogWeb/用户管理功能完善.md:
--------------------------------------------------------------------------------
1 | ### 目录
2 | 1. [判断用户登录状态以及注册、退出](#判断用户登录状态以及注册退出)
3 | 1. [编写博客的数据模型类](#编写博客的数据模型类)
4 | 1. [html显示博客信息](#html显示博客信息)
5 | 1. [重置后台模板与实现用户登录](#重置后台模板与实现用户登录)
6 |
7 | .
.
8 |
9 | > 参考书籍:《跟老齐学 Python:Django实战》
10 |
11 | .
.
12 |
13 | ### *判断用户登录状态以及注册、退出:*
14 | + **下载django**
15 | ```shell
16 | pip3 install django
17 | ```
18 | ```shell
19 | # 如果还没有安装pip3:
20 | sudo apt-get install python3-pip
21 | ```
22 | + **建立django项目**
23 | ```django
24 | # 在项目文件夹下执行指令
25 | django-admin startproject crawlweb
26 | ```
27 |
28 | 但是!执行后会出现下面报错:
29 | ```shell
30 | zsh: command not found: django-admin
31 | ```
32 |
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, render_template, redirect, url_for
2 | from flask_sqlalchemy import SQLAlchemy
3 |
4 | from forms import NewsForm
5 | from datetime import datetime
6 |
7 | app = Flask(__name__)
8 | app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:fmw19990718@localhost:3306/net_news?charset=utf8'
9 | app.config['SECRET_KEY'] = 'a random string'
10 | db = SQLAlchemy(app)
11 |
12 | class News(db.Model):
13 | __tablename__ = 'news'
14 | id = db.Column(db.Integer, primary_key=True)
15 | title = db.Column(db.String(200), nullable=False)
16 | content = db.Column(db.String(2000), nullable=False)
17 | types = db.Column(db.String(10), nullable=False)
18 | image = db.Column(db.String(300), )
19 | author = db.Column(db.String(20), )
20 | view_count = db.Column(db.Integer)
21 | created_at = db.Column(db.DateTime)
22 | is_valid = db.Column(db.Boolean)
23 |
24 | def __repr__(self):
25 | return '' % self.title
26 |
27 |
28 | @app.route('/')
29 | def index():
30 | # 新闻首页
31 | # news_list = News.query.all()
32 | news_list = News.query.filter_by(is_valid=1)
33 | return render_template('index.html', news_list=news_list)
34 |
35 | @app.route('/cat/')
36 | @app.route('/cat//')
37 | def cat(name=None):
38 | # 新闻类别,查询类别为 name 的新闻数据
39 | news_list = News.query.filter(News.types==name)
40 | return render_template('cat.html', name=name, news_list=news_list)
41 |
42 | @app.route('/detail//')
43 | def detail(pk):
44 | # 新闻详情信息
45 | news_obj = News.query.get(pk)
46 | return render_template('detail.html', news_obj=news_obj)
47 |
48 | @app.route('/admin/')
49 | @app.route('/admin//')
50 | def admin(page=None):
51 | # 新闻后台管理首页
52 | if page is None:
53 | page = 1
54 | news_list = News.query.filter_by(is_valid=True).paginate(page=page, per_page=5)
55 | return render_template('admin/index.html', news_list=news_list)
56 |
57 | @app.route('/admin/add/', methods=('GET', 'POST'))
58 | def add():
59 | # 新闻后台数据新增
60 | form = NewsForm()
61 | if form.validate_on_submit():
62 | # 获取数据
63 | new_obj = News(
64 | title = form.title.data,
65 | content = form.content.data,
66 | types = form.types.data,
67 | image = form.image.data,
68 | created_at = datetime.now(),
69 | is_valid = True
70 | )
71 | # 保存数据
72 | db.session.add(new_obj)
73 | db.session.commit()
74 | return redirect(url_for('admin'))
75 | return render_template('admin/add.html', form=form)
76 |
77 | @app.route('/admin/update//', methods=('GET', 'POST'))
78 | def update(pk):
79 | # 新闻后台数据修改
80 | news_obj = News.query.get(pk)
81 | # 如果没有数据,则返回
82 | if not news_obj:
83 | return redirect(url_for('admin'))
84 | form = NewsForm(obj=news_obj)
85 | if form.validate_on_submit():
86 | # 获取数据
87 | news_obj.title = form.title.data
88 | news_obj.content = form.content.data
89 | # 保存数据
90 | db.session.add(news_obj)
91 | db.session.commit()
92 | return redirect(url_for('admin'))
93 | return render_template('admin/update.html', form=form)
94 |
95 | @app.route('/admin/delete//', methods=('GET', 'POST'))
96 | def delete(pk):
97 | # 新闻后台数据删除
98 | news_obj = News.query.get(pk)
99 | if not news_obj:
100 | return 'no'
101 | news_obj.is_valid = False
102 | db.session.add(news_obj)
103 | db.session.commit()
104 | return 'yes'
105 |
106 |
107 | if __name__ == "__main__":
108 | app.run(debug=True)
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/forms.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | from flask_wtf import FlaskForm
4 | from wtforms import StringField, TextAreaField, SubmitField, SelectField, RadioField
5 | from wtforms.validators import DataRequired
6 |
7 |
8 | class NewsForm(FlaskForm):
9 | # 新闻表单
10 | title = StringField(label='新闻标题', validators=[DataRequired('请输入标题')],
11 | description='请输入标题',
12 | render_kw={'required': 'required', 'class': 'form-control'})
13 | content = TextAreaField(label='新闻内容', validators=[DataRequired('请输入内容')],
14 | description='请输入内容',
15 | render_kw={'required': 'required', 'class': 'form-control'})
16 | types = SelectField('新闻类型',
17 | choices=[('推荐', '推荐'), ('百家', '百家'), ('本地', '本地'), ('图片', '图片')])
18 | image = StringField(label='新闻图片',
19 | description='请输入图片地址',
20 | render_kw={'required': 'required', 'class': 'form-control'})
21 | submit = SubmitField('提交')
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/css/index.css:
--------------------------------------------------------------------------------
1 | header > nav {
2 | text-align: center;
3 | }
4 |
5 | header > nav > ul {
6 | display: inline;
7 | white-space: nowrap;
8 | }
9 |
10 | header > nav > ul > li {
11 | list-style: none;
12 | padding: 10px 20px;
13 | display: inline-block;
14 | background: pink;
15 | white-space: nowrap;
16 |
17 | border: 1px solid;
18 | }
19 |
20 | article {
21 | text-align: center;
22 | }
23 |
24 | .list-news {
25 | border: 1px solid black;
26 | margin-top: 10px;
27 | }
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/1.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/2.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/3.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/4.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/5.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/6.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/7.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/8.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/static/img/news/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step5-Python-web/Flask/project/static/img/news/9.png
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/admin/add.html:
--------------------------------------------------------------------------------
1 | {% extends 'admin/admin_base.html' %}
2 |
3 | {% block title %}
4 | 新增新闻
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
52 | {% endblock%}
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/admin/admin_base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {% block title %}
8 | 新闻管理首页
9 | {% endblock %}
10 |
11 |
12 |
13 |
14 |
15 |
16 | {% for message in get_flashed_messages() %}
17 |
18 |
21 |
22 | {% endfor %}
23 |
24 |
80 |
81 |
82 |
83 |
84 |
89 |
90 | {% block content %}
91 |
92 | {% endblock %}
93 |
94 |
95 |
96 |
97 |
98 |
99 | {% block extrajs %}
100 |
101 | {% endblock %}
102 |
103 |
104 |
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/admin/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'admin/admin_base.html' %}
2 |
3 | {% block title %}
4 | 新闻管理首页
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 |
10 |
11 | 编号 |
12 | 新闻标题 |
13 | 类别 |
14 | 添加时间 |
15 | 操作 |
16 |
17 |
18 |
19 | {% for news_obj in news_list.items %}
20 |
21 | {{ news_obj.id }} |
22 | {{ news_obj.title }} |
23 | {{ news_obj.types }} |
24 | {{ news_obj.created_at }} |
25 |
26 | 修改
27 | 删除
28 | |
29 |
30 | {% endfor %}
31 |
32 |
33 |
52 | {% endblock %}
53 |
54 | {% block extrajs %}
55 |
71 | {% endblock %}
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/admin/update.html:
--------------------------------------------------------------------------------
1 | {% extends 'admin/admin_base.html' %}
2 |
3 | {% block title %}
4 | 修改新闻
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
52 | {% endblock %}
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {% block title %}
8 | 首页
9 | {% endblock %}
10 |
11 |
12 |
13 |
24 |
25 |
26 |
27 | {% block content %}
28 |
29 | {% endblock %}
30 |
31 |
32 | {% block extrajs %}
33 |
34 | {% endblock %}
35 |
36 |
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/cat.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | 新闻类别页
5 | {% endblock %}
6 |
7 | {% block content %}
8 | 新闻类别:{{ name }}
9 |
10 | {% for news in news_list %}
11 |
12 |
13 |

14 |
15 |
16 |
17 |
{{ news.created_at }}
18 |
19 |
20 | {% endfor %}
21 | {% endblock %}
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block title %}
4 | 新闻详情页
5 | {% endblock %}
6 |
7 | {% block content %}
8 | {{ news_obj.title }}
9 | {{ news_obj.content }}
10 | {% endblock %}
--------------------------------------------------------------------------------
/step5-Python-web/Flask/project/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block content %}
4 | {% for news in news_list %}
5 |
14 | {% endfor %}
15 | {% endblock %}
--------------------------------------------------------------------------------
/step5-Python-web/README.md:
--------------------------------------------------------------------------------
1 | # 💬Python Web
2 | 目前,Python的网络编程框架已经多达几十个,逐个学习它们并不现实。但这些框架在系统架构和运行环境中有很多共通之处,所以这一节我们会先介绍Web编程的网络基础,以及Python网络框架开发的常用知识,然后会学习四种主流的 Python web 框架。[支持快速建站的框架——Flask](#7-支持快速建站的框架flask)、[企业级开发框架——Django](#5-企业级开发框架django)、[高并发处理框架——Tornado](#6-高并发处理框架tornado)、[底层自定义协议网络框架——Twisted](#8-底层自定义协议网络框架twisted)
3 |
4 |
5 |

6 |
7 |
8 | ---
9 |
10 | ### *📑快捷目录:*
11 | [1. 网页编程语言——前端](#1-网页编程语言前端)
12 |
13 | [2. 计算机网络](#2-计算机网络)
14 |
15 | [3. 数据库及 ORM](#3-数据库及-ORM)
16 |
17 | [4. Python网络框架](#4-Python网络框架)
18 |
19 | [5. 企业级开发框架——Django](#5-企业级开发框架django)
20 |
21 | [6. 高并发处理框架——Tornado](#6-高并发处理框架tornado)
22 |
23 | [7. 支持快速建站的框架——Flask](#7-支持快速建站的框架flask)
24 |
25 | [8. 底层自定义协议网络框架——Twisted](#8-底层自定义协议网络框架twisted)
26 |
27 |
28 |

29 |
30 |
31 | ---
32 |
33 | ## 1. 网页编程语言——前端
34 | + 前端即网站前台部分,运行在PC端,移动端等浏览器上展现给用户浏览的网页。
35 |
36 | + 如果你在之前还没系统的了解过前端,可以在我的另一个库中学习了解。[点我跳转](https://github.com/fmw666/Front-end/)
37 |
38 |
39 |

40 |
41 |
42 | ---
43 |
44 | [返回目录⬆](#快捷目录)
45 |
46 | ## 2. 计算机网络
47 | + 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
48 |
49 | + 如果你在之前还没系统的了解过网络相关知识,可以在我的另一个库中学习了解。[点我跳转](https://github.com/fmw666/Linux/Network/)
50 |
51 |
52 |

53 |
54 |
55 | ---
56 |
57 | [返回目录⬆](#快捷目录)
58 |
59 | ## 3. 数据库及 ORM
60 | ### 数据库
61 | + 为了方便管理和存储数据,对数据进行增删查改,我们往往要用到数据库,而且是基本是必学和必用的。
62 |
63 | + 如果你在之前还没系统的了解过数据库相关知识,可以在我的另一个库中学习了解。[点我跳转](https://github.com/fmw666/Database-System)
64 |
65 | ### ORM(Object-Relational Mapping,对象关系映射)
66 | + ORM的作用是在关系型数据库和业务实体对象之间做一个映射,这样开发者在操作数据库的数据时,就不需要再去和复杂的 SQL 语句打交道,只需简单地操作对象地属性和方法。所有的 ORM 必须具备3方面地基本能力:映射技术、CRUD操作(Create增加、Retrieve读取、Update更新、Delete删除)和缓存优化。
67 |
68 |
69 |

70 |
71 |
72 | ---
73 |
74 | [返回目录⬆](#快捷目录)
75 |
76 | ## 4. Python网络框架
77 |
78 | ---
79 |
80 | [返回目录⬆](#快捷目录)
81 |
82 | ## 5. 企业级开发框架——Django
83 | + Django 是 Python 世界中应用最广泛、发展最成熟的 Web 框架。因为 Django 足够完整,所以使用 Django 本身就可以开发出非常完整的 Web 应用,而无须借助诸如 SQLAlchemy 等其他数据访问组件。
84 |
85 | ### 5.1 Django 综述
86 | + Django 于 2003 年诞生于美国堪萨斯(Kansas)州,最初是劳伦斯出版集团为了用来制作在线新闻 Web 站点而开发的。Django 于 2005 年加入了 BSD 许可证家族,成为开源网络框架。Django 根据比利时的爵士音乐家 [Django Reinhardt](https://en.wikipedia.org/wiki/Django_Reinhardt) 命名,*作者这样命名 Django 意味着 Django 能优雅地演奏(开发)功能丰富的乐曲(Web 应用)*。
87 |
88 |
89 |

90 |
91 |
92 | + Django 相比于 Python 的其他 Web 框架,其功能是最完整的,Django 定义了服务发布、路由映射、模板编程、数据处理的一整套功能。这也意味着 Django 的模块之间紧密耦合,开发者需要学习 Django 自己定义的这一整套技术。Django 的主要特点如下。
93 |
94 | - **完整的文档:** 经过 10 多年的发展和完善,Django 有广泛的应用和完善的在线文档。
95 | - **集成数据访问组件:** Django 的 Model 层自带数据库 ORM 组件。
96 | - **强大的 URL 映射技术:** Django 使用正则表达式管理 URL 映射。
97 | - **后台管理系统自动生成:** 只需要几行简单的配置和代码就可以实现完整的后台数据管理 Web 控制台。
98 | - **错误信息非常完整。**
99 |
100 |
101 |

102 |
103 |
104 | + Django 是遵循 MVC 架构的 Web 开发框架,其主要由以下几部分组成。
105 |
106 | - **管理工具(Management):** 一套内置的创建站点、迁移数据、维护静态文件的命令工具。
107 | - **模型(Model):** 提供数据访问接口和模块,包括数据字段、元数据、数据关系等的定义及操作。
108 | - **视图(View):** Django 的视图层封装了 HTTP Request 和 Response 的一系列操作和数据流,其主要功能包括 URL 映射机制、绑定模板等。
109 | - **模板(Template):** 是一套 Django 自己的页面渲染模板语言,用若干内置的 tags 和 filters 定义页面的生产方式。
110 | - **表单(Form):** 通过内置的数据类型和控件生产 HTML 表单。
111 | - **管理站(Admin):** 通过声明需要管理的 Model,快速生成后台数据管理网站。
112 |
113 |
114 |

115 |
116 |
117 | + Django 的安装及测试
118 |
119 | ```python
120 | pip install django
121 | ```
122 |
123 | ```python
124 | #python
125 | >>>import django
126 | >>>print(django.VERSION)
127 | (2, 1, 7, 'final', 0)
128 | ```
129 |
130 |
131 |

132 |
133 |
134 | ### 5.2 开发 Django 站点
135 | + 建立项目。在进行 Django 开发之前需要先用 django-admin 建立 Django 项目,语法如下:
136 |
137 | ```python
138 | django-admin startproject 站点名称
139 | ```
140 |
141 | ---
142 |
143 | [返回目录⬆](#快捷目录)
144 |
145 | ## 6. 高并发处理框架——Tornado
146 |
147 | ---
148 |
149 | [返回目录⬆](#快捷目录)
150 |
151 | ## 7. 支持快速建站的框架——Flask
152 |
153 | ---
154 |
155 | [返回目录⬆](#快捷目录)
156 |
157 | ## 8. 底层自定义协议网络框架——Twisted
158 |
159 | ---
160 |
161 | [返回目录⬆](#快捷目录)
162 |
163 | ---
164 |
165 |
166 |
169 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/async_demo/requirements.txt:
--------------------------------------------------------------------------------
1 | aiomysql==0.0.20
2 | cffi==1.14.0
3 | cryptography==2.8
4 | pycparser==2.19
5 | PyMySQL==0.9.2
6 | six==1.14.0
7 | tornado==6.0.3
8 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/async_demo/server.py:
--------------------------------------------------------------------------------
1 | # 导入模块
2 | import tornado.ioloop
3 | import tornado.web
4 |
5 | import json
6 |
7 | import aiomysql
8 |
9 | # 创建视图类
10 | class MainHandler(tornado.web.RequestHandler):
11 |
12 | async def get(self):
13 |
14 | # 1. 连接数据库
15 | conn = await aiomysql.connect(host='localhost', port=3306, db='book_manager', user='root', password='fmw19990718', charset='utf8')
16 |
17 | # 使用 aiomysql 异步上下文管理器。类似于 with open,可以不使用 cur.close 对游标关闭
18 | async with conn.cursor() as cur:
19 | await cur.execute("select * from books;")
20 | data = await cur.fetchall()
21 |
22 | '''
23 | # 获得 Cursor 对象
24 | cs1 = await conn.cursor()
25 |
26 | # 2. 执行查询的 sql 语句
27 | await cs1.execute("select * from books;")
28 | # 得到返回的数据
29 | data = await cs1.fetchall()
30 |
31 | # 3. 关闭数据库连接
32 | await cs1.close()
33 | '''
34 | conn.close()
35 |
36 | # 传入模板页面
37 | self.render('index.html', show_list=data)
38 |
39 | async def post(self):
40 | # 得到前端的数据,再插入到数据库
41 |
42 | # 1. 创建一个列表用以接收前端数据
43 | params_list = list()
44 | params_list.append(self.get_argument('btitle'))
45 | params_list.append(self.get_argument('bauthor'))
46 | params_list.append(self.get_argument('bperson'))
47 | params_list.append(self.get_argument('bpub_date'))
48 | params_list.append(self.get_argument('bread'))
49 | params_list.append(self.get_argument('bcomment'))
50 |
51 | # 2. 连接数据库,进行插入
52 | conn = await aiomysql.connect(host='localhost', port=3306, db='book_manager', user='root', password='fmw19990718', charset='utf8')
53 | cs1 = await conn.cursor()
54 | await cs1.execute("insert into books(btitle, bauthor, bperson, bpub_date, bread, bcomment) values (%s, %s, %s, %s, %s, %s)", params_list)
55 | # 提交数据
56 | await conn.commit()
57 | # 关闭连接
58 | await cs1.close()
59 | conn.close()
60 |
61 | # 3. 返回一个 json 格式的数据,或直接返回一个字典
62 | self.write({'data': '添加成功'})
63 |
64 | async def put(self):
65 |
66 | # 1. 得到前端传过来的 body 数据
67 | params_list = list()
68 | params_list.append(self.get_argument('btitle'))
69 | params_list.append(self.get_argument('bauthor'))
70 | params_list.append(self.get_argument('bperson'))
71 | params_list.append(self.get_argument('bpub_date'))
72 | params_list.append(self.get_argument('bread'))
73 | params_list.append(self.get_argument('bcomment'))
74 | params_list.append(self.get_argument('bid'))
75 |
76 | # 2. 连接数据库
77 | conn = await aiomysql.connect(host='localhost', port=3306, db='book_manager', user='root', password='fmw19990718', charset='utf8')
78 | cs1 = await conn.cursor()
79 |
80 | # 3. 执行 sql 更新语句
81 | await cs1.execute("update books set btitle=%s, bauthor=%s, bperson=%s, bpub_date=%s, bread=%s, bcomment=%s where id = %s", params_list)
82 | # 提交
83 | await conn.commit()
84 | # 关闭连接
85 | await cs1.close()
86 | conn.close()
87 |
88 | # 5. 返回对应的数据
89 | self.write({"data": "更新成功"})
90 |
91 | async def delete(self):
92 |
93 | # 1. 得到前端的数据 并 解码
94 | decode_body = self.request.body.decode('utf-8')
95 |
96 | # 2. 转成字典
97 | params_dict = json.loads(decode_body)
98 |
99 | # 3. 连接数据库
100 | conn = await aiomysql.connect(host='localhost', port=3306, db='book_manager', user='root', password='fmw19990718', charset='utf8')
101 | cs1 = await conn.cursor()
102 |
103 | # 4. 执行 sql 更新语句
104 | await cs1.execute("delete from books where id = %(id)s", params_dict)
105 | # 提交
106 | await conn.commit()
107 | # 关闭连接
108 | await cs1.close()
109 | conn.close()
110 |
111 | # 5. 返回对应的数据
112 | self.write({"data": "删除成功"})
113 |
114 | # 程序配置
115 | def make_app():
116 | # 路由配置
117 | return tornado.web.Application([
118 | (r"/", MainHandler),
119 | ],
120 | static_path = './static', # 静态文件夹路径
121 | template_path = './templates' # 模板路径
122 | )
123 |
124 |
125 | # 程序入口
126 | if __name__ == "__main__":
127 | # 加载配置
128 | app = make_app()
129 | # 设置监听
130 | app.listen(8888)
131 | # 开启服务(ioloop 实际上是对 epoll 的封装)
132 | tornado.ioloop.IOLoop.current().start()
133 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/async_demo/static/book.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 | // 删除
3 | $('.del').on('click', function() {
4 | result = $(this).siblings().eq(0).children('input').val()
5 | $.ajax({
6 | url: '/',
7 | dataType: 'json',
8 | type: 'delete',
9 | data: JSON.stringify({id: result}),
10 | success: function(dat) {
11 | alert(dat.data)
12 | $(this).parent().remove()
13 | console.log($(this))
14 | window.location.reload()
15 | }
16 | })
17 | })
18 |
19 | // 更新
20 | $('.update').on('click', function() {
21 | var upTds = $(this).siblings()
22 | dict_data = {}
23 | for (var i=0; i<(upTds.length-1); i++) {
24 | if (i == 0) {
25 | dict_data.bid = upTds.eq(i).children('input').val()
26 | } else if (i == 1) {
27 | dict_data.btitle = upTds.eq(i).children('input').val()
28 | } else if (i == 2) {
29 | dict_data.bauthor = upTds.eq(i).children('input').val()
30 | } else if (i == 3) {
31 | dict_data.bperson = upTds.eq(i).children('input').val()
32 | } else if (i == 4) {
33 | dict_data.bpub_date = upTds.eq(i).children('input').val()
34 | } else if (i == 5) {
35 | dict_data.bread = upTds.eq(i).children('input').val()
36 | } else if (i == 6) {
37 | dict_data.bcomment = upTds.eq(i).children('input').val()
38 | }
39 | }
40 | if (dict_data.bid == "" | dict_data.btitle == "" | dict_data.bauthor == "" | dict_data.bperson == "" | dict_data.bpub_date == "" | dict_data.bread == "" | dict_data.bcomment == "") {
41 | alert('输入内容不能为空!')
42 | return
43 | }
44 | $.ajax({
45 | url: '/',
46 | dataType: 'json',
47 | type: 'put',
48 | data: dict_data,
49 | success: function(dat) {
50 | alert(dat.data)
51 | window.location.reload()
52 | }
53 | })
54 | })
55 |
56 | // 增添
57 | $('.add').on('click', function() {
58 | var addTds = $('.addlist input')
59 | dict_data = {}
60 | for (var i=0; i<(addTds.length-1); i++) {
61 | if (i == 0) {
62 | dict_data.btitle = addTds.eq(i).val()
63 | } else if (i == 1) {
64 | dict_data.bauthor = addTds.eq(i).val()
65 | } else if (i == 2) {
66 | dict_data.bperson = addTds.eq(i).val()
67 | } else if (i == 3) {
68 | dict_data.bpub_date = addTds.eq(i).val()
69 | } else if (i == 4) {
70 | dict_data.bread = addTds.eq(i).val()
71 | } else if (i == 5) {
72 | dict_data.bcomment = addTds.eq(i).val()
73 | }
74 | }
75 | if (dict_data.btitle == "" | dict_data.bauthor == "" | dict_data.bperson == "" | dict_data.bpub_date == "" | dict_data.bread == "" | dict_data.bcomment == "") {
76 | alert('输入内容不能为空!')
77 | return
78 | }
79 | $.post({
80 | url: '/',
81 | dataType: 'json',
82 | data: dict_data,
83 | success: function(dat) {
84 | alert(dat.data)
85 | window.location.reload()
86 | // 清空所有输入框
87 | for (var i=0; i<(addTds.length-1); i++) {
88 | console.log(i)
89 | addTds.eq(i).val("")
90 | }
91 | }
92 | })
93 | })
94 | })
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/async_demo/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | title
7 |
8 |
9 | 图书操作(删、查、改)
10 |
11 |
35 |
36 |
37 |
38 | 新增图书
39 |
40 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/sync_demo/requirements.txt:
--------------------------------------------------------------------------------
1 | PyMySQL==0.9.3
2 | tornado==6.0.3
3 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/sync_demo/server.py:
--------------------------------------------------------------------------------
1 | # 导入模块
2 | import tornado.ioloop
3 | import tornado.web
4 |
5 | from pymysql import connect
6 | import json
7 |
8 | # 创建视图类
9 | class MainHandler(tornado.web.RequestHandler):
10 |
11 | # 请求方式:get、post、put、delete
12 |
13 | # 导入 html 方式1:读取文件
14 | # def get(self):
15 | # # 打开文件返回
16 | # with open('./templates/index.html', 'rb') as f:
17 | # content = f.read()
18 | # self.write(content)
19 |
20 | # 导入 html 方式2:专门用来显示模板内容的方法
21 | def get(self):
22 | # 读取数据库数据,传入给模板页面用以渲染
23 |
24 | # 1. 连接数据库
25 | conn = connect(host='localhost', port=3306, database='book_manager', user='root', password='fmw19990718', charset='utf8')
26 |
27 | # 获得 Cursor 对象
28 | cs1 = conn.cursor()
29 |
30 | # 2. 执行查询的 sql 语句
31 | cs1.execute("select * from books;")
32 | # 得到返回的数据
33 | data = cs1.fetchall()
34 |
35 | # 3. 关闭数据库连接
36 | cs1.close()
37 | conn.close()
38 |
39 | # 传入模板页面
40 | self.render('index.html', show_list=data)
41 |
42 | def post(self):
43 | # 得到前端的数据,再插入到数据库
44 |
45 | # 1. 创建一个列表用以接收前端数据
46 | params_list = list()
47 | params_list.append(self.get_argument('btitle'))
48 | params_list.append(self.get_argument('bauthor'))
49 | params_list.append(self.get_argument('bperson'))
50 | params_list.append(self.get_argument('bpub_date'))
51 | params_list.append(self.get_argument('bread'))
52 | params_list.append(self.get_argument('bcomment'))
53 |
54 | # 2. 连接数据库,进行插入
55 | conn = connect(host='localhost', port=3306, database='book_manager', user='root', password='fmw19990718', charset='utf8')
56 | cs1 = conn.cursor()
57 | cs1.execute("insert into books(btitle, bauthor, bperson, bpub_date, bread, bcomment) values (%s, %s, %s, %s, %s, %s)", params_list)
58 | # 提交数据
59 | conn.commit()
60 | # 关闭连接
61 | cs1.close()
62 | conn.close()
63 |
64 | # 3. 返回一个 json 格式的数据,或直接返回一个字典
65 | self.write({'data': '添加成功'})
66 |
67 | def put(self):
68 |
69 | # 1. 得到前端传过来的 body 数据
70 | params_list = list()
71 | params_list.append(self.get_argument('btitle'))
72 | params_list.append(self.get_argument('bauthor'))
73 | params_list.append(self.get_argument('bperson'))
74 | params_list.append(self.get_argument('bpub_date'))
75 | params_list.append(self.get_argument('bread'))
76 | params_list.append(self.get_argument('bcomment'))
77 | params_list.append(self.get_argument('bid'))
78 |
79 | # 2. 连接数据库
80 | conn = connect(host='localhost', port=3306, database='book_manager', user='root', password='fmw19990718', charset='utf8')
81 | cs1 = conn.cursor()
82 |
83 | # 3. 执行 sql 更新语句
84 | cs1.execute("update books set btitle=%s, bauthor=%s, bperson=%s, bpub_date=%s, bread=%s, bcomment=%s where id = %s", params_list)
85 | # 提交
86 | conn.commit()
87 | # 关闭连接
88 | cs1.close()
89 | conn.close()
90 |
91 | # 5. 返回对应的数据
92 | self.write({"data": "更新成功"})
93 |
94 | def delete(self):
95 |
96 | # 1. 得到前端的数据 并 解码
97 | decode_body = self.request.body.decode('utf-8')
98 |
99 | # 2. 转成字典
100 | params_dict = json.loads(decode_body)
101 |
102 | # 3. 连接数据库
103 | conn = connect(host='localhost', port=3306, database='book_manager', user='root', password='fmw19990718', charset='utf8')
104 | cs1 = conn.cursor()
105 |
106 | # 4. 执行 sql 更新语句
107 | cs1.execute("delete from books where id = %(id)s", params_dict)
108 | # 提交
109 | conn.commit()
110 | # 关闭连接
111 | cs1.close()
112 | conn.close()
113 |
114 | # 5. 返回对应的数据
115 | self.write({"data": "删除成功"})
116 |
117 | # 程序配置
118 | def make_app():
119 | # 路由配置
120 | return tornado.web.Application([
121 | (r"/", MainHandler),
122 | ],
123 | static_path = './static', # 静态文件夹路径
124 | template_path = './templates' # 模板路径
125 | )
126 |
127 |
128 | # 程序入口
129 | if __name__ == "__main__":
130 | # 加载配置
131 | app = make_app()
132 | # 设置监听
133 | app.listen(8888)
134 | # 开启服务(ioloop 实际上是对 epoll 的封装)
135 | tornado.ioloop.IOLoop.current().start()
136 |
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/sync_demo/static/book.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 | // 删除
3 | $('.del').on('click', function() {
4 | result = $(this).siblings().eq(0).children('input').val()
5 | $.ajax({
6 | url: '/',
7 | dataType: 'json',
8 | type: 'delete',
9 | data: JSON.stringify({id: result}),
10 | success: function(dat) {
11 | alert(dat.data)
12 | $(this).parent().remove()
13 | console.log($(this))
14 | window.location.reload()
15 | }
16 | })
17 | })
18 |
19 | // 更新
20 | $('.update').on('click', function() {
21 | var upTds = $(this).siblings()
22 | dict_data = {}
23 | for (var i=0; i<(upTds.length-1); i++) {
24 | if (i == 0) {
25 | dict_data.bid = upTds.eq(i).children('input').val()
26 | } else if (i == 1) {
27 | dict_data.btitle = upTds.eq(i).children('input').val()
28 | } else if (i == 2) {
29 | dict_data.bauthor = upTds.eq(i).children('input').val()
30 | } else if (i == 3) {
31 | dict_data.bperson = upTds.eq(i).children('input').val()
32 | } else if (i == 4) {
33 | dict_data.bpub_date = upTds.eq(i).children('input').val()
34 | } else if (i == 5) {
35 | dict_data.bread = upTds.eq(i).children('input').val()
36 | } else if (i == 6) {
37 | dict_data.bcomment = upTds.eq(i).children('input').val()
38 | }
39 | }
40 | if (dict_data.bid == "" | dict_data.btitle == "" | dict_data.bauthor == "" | dict_data.bperson == "" | dict_data.bpub_date == "" | dict_data.bread == "" | dict_data.bcomment == "") {
41 | alert('输入内容不能为空!')
42 | return
43 | }
44 | $.ajax({
45 | url: '/',
46 | dataType: 'json',
47 | type: 'put',
48 | data: dict_data,
49 | success: function(dat) {
50 | alert(dat.data)
51 | window.location.reload()
52 | }
53 | })
54 | })
55 |
56 | // 增添
57 | $('.add').on('click', function() {
58 | var addTds = $('.addlist input')
59 | dict_data = {}
60 | for (var i=0; i<(addTds.length-1); i++) {
61 | if (i == 0) {
62 | dict_data.btitle = addTds.eq(i).val()
63 | } else if (i == 1) {
64 | dict_data.bauthor = addTds.eq(i).val()
65 | } else if (i == 2) {
66 | dict_data.bperson = addTds.eq(i).val()
67 | } else if (i == 3) {
68 | dict_data.bpub_date = addTds.eq(i).val()
69 | } else if (i == 4) {
70 | dict_data.bread = addTds.eq(i).val()
71 | } else if (i == 5) {
72 | dict_data.bcomment = addTds.eq(i).val()
73 | }
74 | }
75 | if (dict_data.btitle == "" | dict_data.bauthor == "" | dict_data.bperson == "" | dict_data.bpub_date == "" | dict_data.bread == "" | dict_data.bcomment == "") {
76 | alert('输入内容不能为空!')
77 | return
78 | }
79 | $.post({
80 | url: '/',
81 | dataType: 'json',
82 | data: dict_data,
83 | success: function(dat) {
84 | alert(dat.data)
85 | window.location.reload()
86 | // 清空所有输入框
87 | for (var i=0; i<(addTds.length-1); i++) {
88 | console.log(i)
89 | addTds.eq(i).val("")
90 | }
91 | }
92 | })
93 | })
94 | })
--------------------------------------------------------------------------------
/step5-Python-web/Tornado/sync_demo/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | title
7 |
8 |
9 | 图书操作(删、查、改)
10 |
11 |
35 |
36 |
37 |
38 | 新增图书
39 |
40 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/step5-Python-web/helloflask.py:
--------------------------------------------------------------------------------
1 | #encoding:utf-8
2 |
3 | # 从flask这个框架中导入Flask这个类
4 | from flask import Flask
5 |
6 | # 初始化一个Flask对象
7 | # Flask()
8 | # 需要传递一个参数__name__
9 | # 1. 方便flask框架去寻找资源
10 | # 2. 方便flask插件比如Flask-Sqlalchemy出现错误的时候,好去寻找问题所在的位置
11 | app = Flask(__name__)
12 |
13 | # @app.route是一个装饰器
14 | # @开头,并且在函数的上面,说明是装饰器
15 | # 这个装饰器的作用,是做一个url与视图函数的映射
16 | # 127.0.0.1:5000/ -> 去请求hello_world这个函数,然后将结果返回给游览器
17 | @app.route('/')
18 | def hello_world():
19 | return '我是第一个flask程序'
20 |
21 | # 如果当前这个文件是作为入口程序运行,那么就执行app.run()
22 | if __name__ == '__main__':
23 | # app.run()
24 | # 启动一个应用服务器,来接受用户的请求
25 | # while True:
26 | # listen()
27 | app.run()
28 |
--------------------------------------------------------------------------------
/step5-Python-web/urls和视图.md:
--------------------------------------------------------------------------------
1 | ## flask的安装
2 | ### pip安装flask:
3 | 在cmd下```pip install flask```
4 | ### 查看flask版本:
5 | 在cmd下
6 | ```
7 | python
8 | >>>import flask
9 | >>>print(flask.__version__)
10 | ```
11 | ## flask简介:
12 | ```flask```是一款非常流行的```Python Web```框架,出生于2010年,作者是`Armin Ronacher`,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个正式的项目。
13 |
14 | `flask`自2010年发布第一个版本以来,大受欢迎,深得开发者的喜爱,并且在[多个公司]()已经得到了应用,flask能如此流行的原因,可以分为以下几点:
15 |
16 |
17 | - 微框架、简介、只做他需要做的,给开发提供了很大的扩展性。
18 | - Flask和相关的依赖(Jinja2、Werkzeug)设计得非常优秀,用起来很爽。
19 | - 开发效率非常高,比如使用`SQLAlchemy`的`ORM`操作数据库可以节省开发者大量书写`sql`的时间。
20 | - 社会活跃度非常高。
21 |
22 | ## 第一个flask程序:
23 | 建立一个hello.py项目
24 | ```python
25 | #encoding:utf-8
26 |
27 | # 从flask这个框架中导入Flask这个类
28 | from flask import Flask
29 |
30 | # 初始化一个Flask对象
31 | # Flask()
32 | # 需要传递一个参数__name__
33 | # 1. 方便flask框架去寻找资源
34 | # 2. 方便flask插件比如Flask-Sqlalchemy出现错误的时候,好去寻找问题所在的位置
35 | app = Flask(__name__)
36 |
37 | # @app.route是一个装饰器
38 | # @开头,并且在函数的上面,说明是装饰器
39 | # 这个装饰器的作用,是做一个url与视图函数的映射
40 | # 127.0.0.1:5000/ -> 去请求hello_world这个函数,然后将结果返回给游览器
41 | @app.route('/')
42 | def hello_world():
43 | return '我是第一个flask程序'
44 |
45 | # 如果当前这个文件是作为入口程序运行,那么就执行app.run()
46 | if __name__ == '__main__':
47 | # app.run()
48 | # 启动一个应用服务器,来接受用户的请求
49 | # while True:
50 | # listen()
51 | app.run()
52 | ```
53 |
--------------------------------------------------------------------------------
/step6-Crawl/Crawler-system-project/README.md:
--------------------------------------------------------------------------------
1 | # 爬虫项目实战:实现爬虫系统
2 |
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/README.md:
--------------------------------------------------------------------------------
1 | # 爬虫-实战项目源码
2 |
3 | 这里插一张图片吧~
4 |
5 | ## 使用 requests 库请求网站
6 | - ***爬取百度页面 html 信息***
7 | ```python
8 | import requests
9 |
10 | url = 'https://www.baidu.com/'
11 | html = requests.get(url)
12 | print(html.text)
13 | ```
14 | ## 使用 Beautiful Soup 解析网页
15 | - ***爬取纽约市景点信息***
16 | ```python
17 | from bs4 import BeautifulSoup
18 | import requests
19 | '''
20 | 爬取网址:
21 | https://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html
22 | '''
23 | url = 'https://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html'
24 | html = requests.get(url)
25 | soup = BeautifulSoup(html.text, 'lxml')
26 | titles = soup.select('div.listing_title > a[target="_blank"]')
27 | imgs = soup.select('img[width="180"]')
28 |
29 | for title,img in zip(titles,imgs):
30 | data = {
31 | 'title' : title.get_text(),
32 | 'img' : img.get('src')
33 | }
34 | print(data)
35 | ```
36 | - ***爬取斗鱼LOL直播信息***
37 | ```python
38 | from bs4 import BeautifulSoup
39 | import requests
40 |
41 | url = 'https://www.douyu.com/g_LOL'
42 | html = requests.get(url)
43 | soup = BeautifulSoup(html.text, 'lxml')
44 | data = soup.select('#live-list-contentbox > li > a > div.mes > div > h3')
45 | href = soup.select('#live-list-contentbox > li > a')
46 | print(len(data))
47 | for i in range(120):
48 | item_data = data[i]
49 | item_href = href[i]
50 | link = url[:21] + item_href.get('href')
51 | result = {
52 | 'title': item_data.get_text().strip(),
53 | 'link': link
54 | }
55 | print(result)
56 | ```
57 | - ***爬取猫眼电影Top100,并存入文本***
58 | ```python
59 | import requests
60 | from multiprocessing import Pool
61 | from requests.exceptions import RequestException
62 | import re
63 | import json
64 |
65 | def get_one_page(url):
66 | try:
67 | response = requests.get(url)
68 | if response.status_code == 200:
69 | return response.text
70 | return None
71 | except RequestException:
72 | return None
73 |
74 | def parse_one_page(html):
75 | pattern = re.compile('.*?board-index.*?>(\d+).*?data-src="(.*?)".*?name">(.*?).*?star">(.*?).*?releasetime">(.*?)'
77 | + '.*?integer">(.*?).*?fraction">(.*?).*?', re.S)
78 | items = re.findall(pattern, html)
79 | for item in items:
80 | yield {
81 | 'index': item[0],
82 | 'image': item[1],
83 | 'title': item[2],
84 | 'actor': item[3].strip()[3:],
85 | 'time' : item[4].strip()[5:],
86 | 'score': item[5] + item[6]
87 | }
88 |
89 | def clear_file(file):
90 | with open(file, 'w', encoding='utf-8') as f:
91 | f.seek(0)
92 | f.truncate()
93 | f.close()
94 |
95 | def write_to_file(content):
96 | with open('maoyanTop100.txt', 'a', encoding='utf-8') as f:
97 | # clear_file('maoyanTop100.txt')
98 | f.write(json.dumps(content, ensure_ascii=False) + '\n')
99 | f.close()
100 |
101 | def main(offset):
102 | url = 'https://maoyan.com/board/4?offset=' + str(offset)
103 | html = get_one_page(url)
104 | for item in parse_one_page(html):
105 | print(item)
106 | write_to_file(item)
107 |
108 | if __name__ == '__main__':
109 | pool = Pool()
110 | pool.map(main, [i*10 for i in range(10)])
111 | ```
112 | - ***爬取bilibili单页视频信息***
113 | ```python
114 | import requests
115 | from bs4 import BeautifulSoup
116 |
117 | url = 'https://search.bilibili.com/all?keyword=python'
118 | html = requests.get(url)
119 | Soup = BeautifulSoup(html.text, 'lxml')
120 | images = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > a > div > div.lazy-img > img')
121 | titles = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > div > div.headline.clearfix > a')
122 | urls = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > a')
123 |
124 | fp = open('crawl/text-pro2/result.txt', 'a', encoding='utf-8')
125 | fp.seek(0)
126 | fp.truncate()
127 | order = 1
128 | for title,url,image in zip(titles,urls,images):
129 | data = {
130 | 'title' : title.get_text(),
131 | 'url' : 'https:' + url.get('href'),
132 | 'image' : image.get('src')
133 | }
134 | fp.write(str(order)+'.'+data['title']+ \
135 | '\n' + ' ' + data['url']+data['image']+'\n')
136 | order += 1
137 | fp.close()
138 | ```
139 | - ***爬取白蛇缘起豆瓣影评***
140 | ```python
141 | from bs4 import BeautifulSoup
142 | import requests
143 | import time
144 |
145 | # 爬取前5页(100条)评论
146 | urls = ['https://movie.douban.com/subject/30331149/comments?start={}&limit=20&sort=new_score&status=P'.format(str(i)) for i in range(0, 100, 20)]
147 | # 全局变量索引
148 | index = 1
149 |
150 | def get_info_to_txt(url,data=None):
151 | html = requests.get(url)
152 | soup = BeautifulSoup(html.text,'lxml')
153 | users = soup.select('span.comment-info > a')
154 | dates = soup.select('span.comment-info > span.comment-time')
155 | conts = soup.select('div.comment > p > span')
156 |
157 | global index
158 | with open('白蛇缘起豆瓣影评.txt','w',encoding='utf-8') as f:
159 | page = index // 20 + 1
160 | for user, date, cont in zip(users, dates, conts):
161 | user_name = user.get_text()
162 | user_id = user.get('href')[30:].rstrip('/')
163 | date_time = date.get_text().strip()
164 | content = cont.get_text().strip()
165 |
166 | f.write(user_name+' ('+user_id+')\n'+date_time+'\n'+content+'\n'+'-------------'+'\n')
167 | print('爬取第{}条'.format(index))
168 | index += 1
169 | time.sleep(1)
170 | print('----------爬取第{}页完成----------'.format(page))
171 |
172 | f.close()
173 |
174 | for url in urls:
175 | get_info_to_txt(url)
176 | ```
177 | - ***通过访问手机端爬取58同城商品信息***
178 | ```python
179 | from bs4 import BeautifulSoup
180 | import requests
181 |
182 | headers = {
183 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1',
184 | 'Cookie': 'f=n; id58=c5/njVxX0KFx5NhuR0H4Ag==; city=bj; 58home=bj; 58tj_uuid=a06e80b8-1250-4f67-a7f7-89aece13e16c; new_uv=1; utm_source=; spm=; init_refer=; als=0; xxzl_deviceid=kV1ATXiudAWv5zyZcxuABiO67foT3kEok%2FQahFJHx1bAYi79lOMzAMixZqPLQKs3; sessionid=29cee45d-54fb-4071-8db7-64445e223d07; new_session=0; gr_user_id=68904093-7ace-4b7b-9ae9-2e2196334187; gr_session_id_98e5a48d736e5e14=17efbb4b-ce29-409b-9028-ec36f6596201; _ga=GA1.2.803555990.1549259044; _gid=GA1.2.155562628.1549259044; Hm_lvt_e2d6b2d0ec536275bb1e37b421085803=1549259054; final_history=37012114400913; wmda_uuid=d641576fae76e691b9d99f42786c554b; wmda_new_uuid=1; wmda_session_id_1409632296065=1549259055478-7eb9c6c0-63cc-b35b; Hm_lpvt_e2d6b2d0ec536275bb1e37b421085803=1549259538; ppStore_fingerprint=C9371F482F4270E49828E3F45A3ED5A2572F9698D6357955%EF%BC%BF1549259539179; _gat=1; device=m; cookieuid=91b5266f-e186-4729-93ba-662bfe9b1db5; wmda_session_id_1444510081921=1549259578897-1feee481-e0a4-2696; wmda_visited_projects=%3B1409632296065%3B1444510081921; gr_session_id_8154da2f94e51dff=b9687de6-5742-4ba1-8a4e-917f8a1c39c1; qz_gdt=; GA_GTID=0d409654-02fb-3c93-8896-17afff5623d8; Hm_lvt_13822dc0c5601dfc5165fd2b6c48b91d=1549259580; Hm_lpvt_13822dc0c5601dfc5165fd2b6c48b91d=1549259580; gr_session_id_8154da2f94e51dff_b9687de6-5742-4ba1-8a4e-917f8a1c39c1=true; _sale_detail_show_time_=2'
185 | }
186 | url = 'https://bj.58.com/pingbandiannao/37012114400913x.shtml?psid=198261563203064481199563272&entinfo=37012114400913_p&slot=-1&iuType=p_1&PGTID=0d305a36-0000-1f31-4c9d-431e2e1be1a2&ClickID=1'
187 |
188 | def get_item_info(url):
189 | html = requests.get(url, headers=headers)
190 | soup = BeautifulSoup(html.text, 'lxml')
191 | data = {
192 | 'title': soup.title.text.strip(),
193 | 'price': soup.select('div.titleArea-price')[0].get_text().strip(),
194 | 'date': soup.select('p.time')[0].get_text().strip(),
195 | 'area': soup.select('.icon-location')[0].get_text().strip()
196 | }
197 | print(data)
198 |
199 | get_item_info(url)
200 | ```
201 |
202 | ## 使用 MongoDB 存入数据
203 | - ***存入豆瓣流浪地球短评***
204 | ```python
205 | from bs4 import BeautifulSoup
206 | import requests
207 | import time
208 | import pymongo
209 |
210 | client = pymongo.MongoClient('localhost',27017)
211 | movie = client['movie']
212 | liulangdiqiu = movie['liulangdiqiu']
213 |
214 | # 爬取前5页(100条)评论
215 | urls = ['https://movie.douban.com/subject/26266893/comments?start={}&limit=20&sort=new_score&status=P'.format(str(i)) for i in range(100, 120, 20)]
216 |
217 | # 全局变量索引
218 | index = 1
219 |
220 | def get_info_to_db(url):
221 | html = requests.get(url)
222 | soup = BeautifulSoup(html.text,'lxml')
223 |
224 | users_img = soup.select('div.avatar > a > img')
225 | users = soup.select('span.comment-info > a')
226 | dates = soup.select('span.comment-info > span.comment-time')
227 | stars = soup.select('span.comment-info > span.rating')
228 | votes = soup.select('span.comment-vote > span')
229 | contents = soup.select('div.comment > p > span')
230 | print(stars)
231 | for user_img,user,date,star,vote,content in zip(users_img,users,dates,stars,votes,contents):
232 | data = {
233 | 'user_img' : user_img.get('src'),
234 | 'user_name': user.get_text(),
235 | 'user_id' : user.get('href')[30:].rstrip('/'),
236 | 'date' : date.get_text().strip(),
237 | 'star' : star.get('class')[0].strip('allstar')[:1],
238 | 'vote' : vote.get_text(),
239 | 'content ' : content.get_text().strip()
240 | }
241 | liulangdiqiu.insert_one(data)
242 | global index
243 | print('插入第{}条完成...'.format(index))
244 | index += 1
245 | # print(data)
246 |
247 | for url in urls:
248 | get_info_to_db(url)
249 | ```
250 |
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/maoyanTop100.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from multiprocessing import Pool
3 | from requests.exceptions import RequestException
4 | import re
5 | import json
6 |
7 | def get_one_page(url):
8 | try:
9 | response = requests.get(url)
10 | if response.status_code == 200:
11 | return response.text
12 | return None
13 | except RequestException:
14 | return None
15 |
16 | def parse_one_page(html):
17 | pattern = re.compile('.*?board-index.*?>(\d+).*?data-src="(.*?)".*?name">(.*?).*?star">(.*?).*?releasetime">(.*?)'
19 | + '.*?integer">(.*?).*?fraction">(.*?).*?', re.S)
20 | items = re.findall(pattern, html)
21 | for item in items:
22 | yield {
23 | 'index': item[0],
24 | 'image': item[1],
25 | 'title': item[2],
26 | 'actor': item[3].strip()[3:],
27 | 'time' : item[4].strip()[5:],
28 | 'score': item[5] + item[6]
29 | }
30 |
31 | def clear_file(file):
32 | with open(file, 'w', encoding='utf-8') as f:
33 | f.seek(0)
34 | f.truncate()
35 | f.close()
36 |
37 | def write_to_file(content):
38 | with open('maoyanTop100.txt', 'a', encoding='utf-8') as f:
39 | # clear_file('maoyanTop100.txt')
40 | f.write(json.dumps(content, ensure_ascii=False) + '\n')
41 | f.close()
42 |
43 | def main(offset):
44 | url = 'https://maoyan.com/board/4?offset=' + str(offset)
45 | html = get_one_page(url)
46 | for item in parse_one_page(html):
47 | print(item)
48 | write_to_file(item)
49 |
50 | if __name__ == '__main__':
51 | pool = Pool()
52 | pool.map(main, [i*10 for i in range(10)])
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/爬取bilibili单页视频信息.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from bs4 import BeautifulSoup
3 |
4 | url = 'https://search.bilibili.com/all?keyword=python'
5 | html = requests.get(url)
6 | Soup = BeautifulSoup(html.text, 'lxml')
7 | images = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > a > div > div.lazy-img > img')
8 | titles = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > div > div.headline.clearfix > a')
9 | urls = Soup.select('#server-search-app > div.contain > div.body-contain > div > div.result-wrap.clearfix > ul > li > a')
10 |
11 | fp = open('crawl/text-pro2/result.txt', 'a', encoding='utf-8')
12 | fp.seek(0)
13 | fp.truncate()
14 | order = 1
15 | for title,url,image in zip(titles,urls,images):
16 | data = {
17 | 'title' : title.get_text(),
18 | 'url' : 'https:' + url.get('href'),
19 | 'image' : image.get('src')
20 | }
21 | fp.write(str(order)+'.'+data['title']+ \
22 | '\n' + ' ' + data['url']+data['image']+'\n')
23 | order += 1
24 | fp.close()
25 |
26 |
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/爬取白蛇缘起豆瓣影评.py:
--------------------------------------------------------------------------------
1 | from bs4 import BeautifulSoup
2 | import requests
3 | import time
4 |
5 | # 爬取前5页(100条)评论
6 | urls = ['https://movie.douban.com/subject/30331149/comments?start={}&limit=20&sort=new_score&status=P'.format(str(i)) for i in range(0, 100, 20)]
7 | # 全局变量索引
8 | index = 1
9 |
10 | def get_info_to_txt(url,data=None):
11 | html = requests.get(url)
12 | soup = BeautifulSoup(html.text,'lxml')
13 | users = soup.select('span.comment-info > a')
14 | dates = soup.select('span.comment-info > span.comment-time')
15 | conts = soup.select('div.comment > p > span')
16 |
17 | global index
18 | with open('白蛇缘起豆瓣影评.txt','w',encoding='utf-8') as f:
19 | page = index // 20 + 1
20 | for user, date, cont in zip(users, dates, conts):
21 | user_name = user.get_text()
22 | user_id = user.get('href')[30:].rstrip('/')
23 | date_time = date.get_text().strip()
24 | content = cont.get_text().strip()
25 |
26 | f.write(user_name+' ('+user_id+')\n'+date_time+'\n'+content+'\n'+'-------------'+'\n')
27 | print('爬取第{}条'.format(index))
28 | index += 1
29 | time.sleep(1)
30 | print('----------爬取第{}页完成----------'.format(page))
31 |
32 | f.close()
33 |
34 | for url in urls:
35 | get_info_to_txt(url)
36 |
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/爬取纽约市景点信息.py:
--------------------------------------------------------------------------------
1 | from bs4 import BeautifulSoup
2 | import requests
3 | '''
4 | 爬取网址:
5 | https://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html
6 | '''
7 | url = 'https://www.tripadvisor.cn/Attractions-g60763-Activities-New_York_City_New_York.html'
8 | html = requests.get(url)
9 | soup = BeautifulSoup(html.text, 'lxml')
10 | titles = soup.select('div.listing_title > a[target="_blank"]')
11 | imgs = soup.select('img[width="180"]')
12 |
13 | for title,img in zip(titles,imgs):
14 | data = {
15 | 'title' : title.get_text(),
16 | 'img' : img.get('src')
17 | }
18 | print(data)
--------------------------------------------------------------------------------
/step6-Crawl/Learn-from-Projects/通过访问手机端爬取58同城商品信息.py:
--------------------------------------------------------------------------------
1 | from bs4 import BeautifulSoup
2 | import requests
3 |
4 | headers = {
5 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1',
6 | 'Cookie': 'f=n; id58=c5/njVxX0KFx5NhuR0H4Ag==; city=bj; 58home=bj; 58tj_uuid=a06e80b8-1250-4f67-a7f7-89aece13e16c; new_uv=1; utm_source=; spm=; init_refer=; als=0; xxzl_deviceid=kV1ATXiudAWv5zyZcxuABiO67foT3kEok%2FQahFJHx1bAYi79lOMzAMixZqPLQKs3; sessionid=29cee45d-54fb-4071-8db7-64445e223d07; new_session=0; gr_user_id=68904093-7ace-4b7b-9ae9-2e2196334187; gr_session_id_98e5a48d736e5e14=17efbb4b-ce29-409b-9028-ec36f6596201; _ga=GA1.2.803555990.1549259044; _gid=GA1.2.155562628.1549259044; Hm_lvt_e2d6b2d0ec536275bb1e37b421085803=1549259054; final_history=37012114400913; wmda_uuid=d641576fae76e691b9d99f42786c554b; wmda_new_uuid=1; wmda_session_id_1409632296065=1549259055478-7eb9c6c0-63cc-b35b; Hm_lpvt_e2d6b2d0ec536275bb1e37b421085803=1549259538; ppStore_fingerprint=C9371F482F4270E49828E3F45A3ED5A2572F9698D6357955%EF%BC%BF1549259539179; _gat=1; device=m; cookieuid=91b5266f-e186-4729-93ba-662bfe9b1db5; wmda_session_id_1444510081921=1549259578897-1feee481-e0a4-2696; wmda_visited_projects=%3B1409632296065%3B1444510081921; gr_session_id_8154da2f94e51dff=b9687de6-5742-4ba1-8a4e-917f8a1c39c1; qz_gdt=; GA_GTID=0d409654-02fb-3c93-8896-17afff5623d8; Hm_lvt_13822dc0c5601dfc5165fd2b6c48b91d=1549259580; Hm_lpvt_13822dc0c5601dfc5165fd2b6c48b91d=1549259580; gr_session_id_8154da2f94e51dff_b9687de6-5742-4ba1-8a4e-917f8a1c39c1=true; _sale_detail_show_time_=2'
7 | }
8 | url = 'https://bj.58.com/pingbandiannao/37012114400913x.shtml?psid=198261563203064481199563272&entinfo=37012114400913_p&slot=-1&iuType=p_1&PGTID=0d305a36-0000-1f31-4c9d-431e2e1be1a2&ClickID=1'
9 |
10 | # .uv
11 | def get_item_info(url):
12 | html = requests.get(url, headers=headers)
13 | soup = BeautifulSoup(html.text, 'lxml')
14 | data = {
15 | 'title': soup.title.text.strip(),
16 | 'price': soup.select('div.titleArea-price')[0].get_text().strip(),
17 | 'date': soup.select('p.time')[0].get_text().strip(),
18 | 'area': soup.select('.icon-location')[0].get_text().strip()
19 | }
20 | print(data)
21 |
22 | get_item_info(url)
23 |
--------------------------------------------------------------------------------
/step6-Crawl/RE/README.md:
--------------------------------------------------------------------------------
1 | # 正则表达式
2 |
--------------------------------------------------------------------------------
/step6-Crawl/README.md:
--------------------------------------------------------------------------------
1 | # 💬Python3 网络爬虫
2 | "得数据者得天下"。在大数据盛行的今天,你或许很容易能在网上看到什么"年度总结",这些东西就是一系列的数据。网上还有很流行的词云,也是通过爬虫爬取下来的数据整理的。总之,会爬虫者得数据,得数据者得天下。
3 |
4 |
5 |

6 |
7 |
8 |
9 | ## *📑 章节目录:*
10 | #### [0. 正则表达式](#)
11 |
12 | #### [1. 开发环境配置](#1-开发环境配置-1)
13 |
14 | #### [2. 爬虫基础](#2)
15 |
16 | #### [3. 基本库的使用](#3)
17 |
18 | #### [4. 解析库的使用](#4)
19 |
20 | #### [5. 数据存储](#5)
21 |
22 | #### [6. Ajax 数据爬取](#6)
23 |
24 | #### [7. 动态渲染页面爬取](#7)
25 |
26 | #### [8. 验证码的识别](#8)
27 |
28 | #### [9. 代理的使用](#9)
29 |
30 | #### [10. 模拟登录](#10)
31 |
32 | #### [11. App 的爬取](#11)
33 |
34 | #### [12. pyspider 框架的使用](#12)
35 |
36 | #### [13. Scrapy 框架的使用](#13)
37 |
38 | #### [14. 分布式爬虫](#14)
39 |
40 | #### [15. 分布式爬虫的部署](#15)
41 |
42 |
43 |

44 |
45 |
46 | ## 1. 开发环境配置
47 | ⚙ 安装库的方法有很多种,但我们选用最简单的第三方包管理工具 **[pip](#no-jump)** 来安装。使用的方法很简单,只需要打开命令行,输入:
48 |
49 | ```python
50 | pip install ***
51 | ```
52 |
53 |
54 |
55 | ### *📜 目录:*
56 | **[1.1. 请求库的安装](#11-请求库的安装)**
57 |
58 | [- requests 的安装](#1.1.1)
59 |
60 | [- Selenium 的安装](#1.1.2)
61 |
62 | **[1.2. 解析库的安装](#12-解析库的安装)**
63 |
64 | **[1.3. 数据库的安装](#1.3)**
65 |
66 | **[1.4. 存储库的安装](#1.4)**
67 |
68 | ---
69 |
70 | ### 1.1. 请求库的安装
71 |
72 |
73 |

74 |
75 |
76 | ***📚 [requests 的安装](#1.1.1)***
77 |
78 | ```cmd
79 | pip install requests
80 | ```
81 |
82 | ***📚 [Selenium 的安装](#1.1.2)***
83 |
84 | [Selenium](#no-jump) 是一个自动化测试工具,利用它我们可以驱动浏览器执行特定的动作,如[点击、下拉](#no-jump)等等操作,对于一些 [JavaScript](#no-jump) 渲染的页面来说,此种抓取方式非常有效。
85 |
86 | ```pip
87 | pip install selenium
88 | ```
89 |
90 | ***📚 [ChromeDriver 的安装](#1.1.3)***
91 |
92 | 暂时未更~
93 |
94 |
95 |
96 | ### 1.2. 解析库的安装
97 |
98 |
99 |

100 |
101 |
102 | ***📚 [lxml 的安装](#1.2.1)***
103 |
104 | [lxml](#no-jump) 是Python的一个解析库,支持 [HTML 和 XML 的解析](#no-jump),支持 [XPtah](#no-jump) 解析方式,而且解析效率非常高。
105 |
106 | ```cmd
107 | pip install lxml
108 | ```
109 |
110 | ---
111 |
112 | [返回目录⬆](#-章节目录)
113 |
114 |
115 |
116 |
117 |
118 | ---
119 |
120 |
121 |
124 |
--------------------------------------------------------------------------------
/step6-Crawl/Regular-Expression/README.md:
--------------------------------------------------------------------------------
1 | 123
2 |
--------------------------------------------------------------------------------
/step6-Crawl/python-re实例.md:
--------------------------------------------------------------------------------
1 | # 《Python 正则表达式 之 实战》
2 | ## 爬取 HTML 文档的字符编码
3 | 网页中通常是将字符编码信息放在 [\](#welcome) 头部信息的 [\](#welcome) 标签中。所以我们首先利用爬虫,爬取到网站的所有 html 内容:
4 | ```python
5 | import requests
6 | from bs4 import BeautifulSoup
7 |
8 | url = 'http://www.baidu.com/'
9 |
10 | html = requests.get(url)
11 | ```
12 |
13 | 利用正则表达式,得到 [\](#welcome) 标签中的所有内容:
14 | ```python
15 | head = re.findall(r'.*', html.text)
16 | ```
17 |
18 | 注意,在 HTML 文档中,规定字符编码有两种格式,如下所示:
19 | ```python
20 | htmlstr1 = ''
21 | htmlstr2 = ''
22 | ```
23 |
24 | 要得到统一的规则是,字符编码全在`'charset='`后面,但是 `htmlstr1` 中比 `htmlstr2` 少了一个双引号 `"` ,所以我们得想办法忽略掉这个 `"` 引号的影响。
25 |
26 | 如果我们单纯的用 或 `|` ,比如 `("|)` ,双引号或者空格来匹配,是匹配不了的。这时候必须要用到正则表达式里一个[无捕获组 '(?:)'](#welcome)。
27 |
28 | 如:[[?:dog|cat]](#welcome) 它的有效范围是 [?:](#welcome) 后面 [|](#welcome)两边的整条规则。所以这里如果是 [(?:"|)](#welcome)(等价于[(?:|")](#welcome)),相当于匹配双引号 `"` 和一个空白字符,即相当于忽略掉双引号 `"` 的影响。
29 |
30 | 整体代码如下:
31 | ```python
32 | import requests
33 | from bs4 import BeautifulSoup
34 | import re
35 |
36 | url = 'http://www.baidu.com/'
37 |
38 | html = requests.get(url)
39 | soup = BeautifulSoup(html.text,'lxml')
40 | head = re.findall(r'.*', html.text)
41 | # 注意每次 re.findall() 返回的是一个列表
42 | charset = re.findall(r'charset=(?:|")([\w-]+)', head[0])
43 | print(charset[0])
44 | ```
45 |
46 | ## 第二个
47 |
--------------------------------------------------------------------------------
/step6-Crawl/sicnu-student-crawl/README.md:
--------------------------------------------------------------------------------
1 | # 学生信息爬虫
2 |
3 | python 3环境 + 依赖库:requests 和beautifulsoup4.
4 |
5 | 安装命令如下
6 | ```python
7 | pip install requests
8 |
9 | pip install beautifulsoup4
10 | ```
11 |
12 | ## 运行命令
13 |
14 | ```python
15 | python crawl.py
16 | ```
17 |
18 |
19 | ## 遍历ALL学院+所有年级+班别+学号
20 | 2015(入学年级)-11(计算机科学学院)-02(2班)-16(16号)
21 | ## [student.py](student.py)
22 |
23 | 获取学生信息
24 |
25 | ## [college_list.py](college_list.py)
26 |
27 | 获取所有的学院
28 |
29 |
30 | ## [crawl.py](crawl.py)
31 |
32 | 爬虫主入口
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/step6-Crawl/sicnu-student-crawl/college_list.csv:
--------------------------------------------------------------------------------
1 | 01,文学院
2 | 02,法学院
3 | 03,外国语学院
4 | 04,历史文化与旅游学院
5 | 05,教育科学学院
6 | 06,数学与软件科学学院
7 | 07,物理与电子工程学院
8 | 08,化学与材料科学学院
9 | 09,生命科学学院
10 | 10,地理与资源科学学院
11 | 11,计算机科学学院
12 | 12,经济与管理学院
13 | 14,体育学院
14 | 15,马克思主义学院
15 | 17,教师教育与心理学院
16 | 18,工学院
17 | 19,商学院
18 | 25,基础教学学院
19 | 27,美术学院
20 | 28,音乐学院
21 | 29,舞蹈学院
22 | 42,影视与传媒学院
23 | 53,服装与设计艺术学院
24 | 33,国际教育学院
25 | 37,应用技术学院
26 | 39,职业技术学院
27 | 22,军事教研室
28 | 23,图书馆
29 | 24,语委办
30 | 36,学生工作部
31 | 91,继续教育学院
32 | 96,保卫处
33 | 41,校医院
34 | 98,招生就业处
35 | 20,美育学校
36 | 30,新闻与传播学院
37 | 32,数字媒体学院
38 | 35,电影电视学院
39 | 43,大学科技园
40 | 55,广元师范学校办学点
41 | 62,凉山民族师范学校办学点
42 | 94,研究生学院
--------------------------------------------------------------------------------
/step6-Crawl/sicnu-student-crawl/college_list.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import csv
4 |
5 | def get_college_list():
6 | with open('college_list.csv',encoding="utf8") as csvfile:
7 | readCSV = csv.reader(csvfile, delimiter=',')
8 | college_list = []
9 | for row in readCSV:
10 | college = {}
11 | college['code'] = row[0]
12 | college['name'] = row[1]
13 | college_list.append(college)
14 | return college_list
15 |
16 |
--------------------------------------------------------------------------------
/step6-Crawl/sicnu-student-crawl/crawl.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from bs4 import BeautifulSoup
3 | from urllib import request
4 | import os
5 | import json
6 | import csv
7 |
8 | from student import get_student_detail
9 |
10 | from college_list import get_college_list
11 | college_list = get_college_list()
12 |
13 | for college in college_list[11:13]:
14 | for year_num in range(2015, 2018):
15 | students = []
16 | college_code = college['code']
17 | for class_num in range(1, 20):
18 | if class_num <= 10:
19 | class_code = str(year_num) + college_code + \
20 | "0" + str(class_num)
21 | else:
22 | class_code = str(year_num) + college_code + str(class_num)
23 | file_path = "%s/%s/%s" % (college['name'], year_num, class_num)
24 | for num in range(1, 100):
25 | card_code = ''
26 | if num < 10:
27 | card_code = class_code + "0" + str(num)
28 | else:
29 | card_code = class_code + str(num)
30 | student = get_student_detail(card_code)
31 | if student is None:
32 | break
33 | if os.path.exists(file_path) is False:
34 | os.makedirs(file_path)
35 | if 'pic_url' in student:
36 | try:
37 | request.urlretrieve(
38 | student['pic_url'], "./%s/%s-%s.jpg" % (file_path, student['number'], student['name']))
39 | except:
40 | print("urlretrieve pic error,url:" +
41 | student['pic_url'])
42 | students.append(student)
43 | print("爬取%s结束!" % (file_path))
44 | if students is None:
45 | continue
46 | with open("%s/%s.csv" % (college['name'], str(year_num)), 'w+', newline='', encoding="utf8") as csv_file:
47 | fieldnames = ['college', 'class', 'major',
48 | 'number', 'name', 'gender', 'nation', 'pic_url']
49 | writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
50 | writer.writeheader()
51 | writer.writerows(students)
52 |
--------------------------------------------------------------------------------
/step6-Crawl/sicnu-student-crawl/student.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from bs4 import BeautifulSoup
3 |
4 |
5 | def get_student_detail(card_code):
6 | url = "http://202.115.194.53:2222/"
7 | querystring = {"CardType": "StudentCard",
8 | "stdCardID": "", "cardCode": card_code}
9 | headers = {
10 | 'Connection': "keep-alive",
11 | 'Cache-Control': "no-cache",
12 | 'Upgrade-Insecure-Requests': "1",
13 | 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
14 | 'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
15 | 'Accept-Encoding': "gzip, deflate",
16 | 'Accept-Language': "zh-CN,zh;q=0.9",
17 | 'Postman-Token': "d60c2ab9-a273-4e3b-a0b3-000d92884325"
18 | }
19 | response = requests.request(
20 | "GET", url, headers=headers, params=querystring)
21 | soup = BeautifulSoup(response.text, "html.parser")
22 | student_number = soup.find("span", id="lblStdNum")
23 | student_name = soup.find("span", id="lblName")
24 | student_class = soup.find("span", id="lblClass")
25 | college = soup.find("span", id="lblCollege")
26 | major = soup.find("span", id="lblMajor")
27 | gender = soup.find("span", id="lblSex")
28 | nation = soup.find("span", id="lblNation")
29 | student_pic_url = soup.find("img", id="usePhoto")
30 | student = {}
31 | if student_number and student_name.text is not '':
32 | student['name'] = student_name.text
33 | student['number'] = student_number.text
34 | student['class'] = student_class.text
35 | student['college'] = college.text
36 | student['major'] = major.text
37 | student['gender'] = gender.text
38 | student['nation'] = nation.text
39 | if student_pic_url:
40 | student['pic_url'] = "http://202.115.194.53:2222/" + \
41 | student_pic_url['src']
42 | return student
43 | else:
44 | return None
45 |
46 |
--------------------------------------------------------------------------------
/step6-Crawl/正则表达式/README.md:
--------------------------------------------------------------------------------
1 | 123
2 |
--------------------------------------------------------------------------------
/step7-Data-Analysis/README.md:
--------------------------------------------------------------------------------
1 | # 💬《数据分析及可视化》
2 |
3 | 所谓数据分析,就是将“庞大”的数据提炼出对社会/个人有价值的信息内容。最常见的就是公司或企业 CSV 或 EXCEL 文件,需要通过一定的技术手段将部分信息处理(过滤/整合/加工)为需求信息。
4 |
5 | > ⭐ 数据处理模块:numpy、pandas;绘图模块:matplotlib、Seaborn;
6 | >> 数据分析三剑客:numpy、pandas、matplotlib
7 |
8 | ---
9 |
10 | ## 📚 目录
11 |
12 | 1. **[运行环境:Jupyter]()**
13 |
14 | 1. **[数据处理:numpy 模块]()**
15 |
16 | 1. **[数据处理:pandas 模块]()**
17 |
18 | 1. **[可视化:matplotlib 绘图]()**
19 |
20 | 1. **[可视化:Seaborn 绘图]()**
21 |
22 | ---
23 |
24 |
25 |
--------------------------------------------------------------------------------
/step7-Data-Analysis/docs/01-pre.md:
--------------------------------------------------------------------------------
1 | ## 💬 重要的 Python 库
2 |
3 | > 库/包的安装基于 **免费的 Anaconda 发布版** 来管理。
4 |
5 | ### NumPy
6 |
7 | NumPy()是 *Numerical Python* 的简写,是 Python 数值计算的基石。
8 |
9 | ### Pandas
10 |
11 | Pandas 的名字来源是 *panel data*,这是计量经济学中针对多维结构化数据集的术语。Pandas 也是 *Python data analysis*(Python 数据分析)自身的简写短语。
12 |
13 | Pandas()提供了高级数据结构和函数,这些数据结构和函数的设计使得利用结构化、表格化数据的工作快速、简单、有表现力。
14 |
15 | ### IPython 与 Jupyter
16 |
17 | IPython 项目()开始于 2001 年,由 Fernando 发起,旨在开发一个更具交互性的 Python 解释器。
18 |
19 | 2014 年,Fernando 与 IPython 团队发布了 Jupyter 项目(),此项目旨在设计一个适用于更多语言的交互式计算工具。
20 |
21 | IPython 系统目前可以作为一个内核用于在 Jupyter 中使用 Python。
22 |
23 | ### SciPy
24 |
25 | SciPy()是科学计算领域针对不同标准问题域的包集合。以下是 SciPy 中包含的一些包:
26 |
27 | + scipy.integrate
28 |
29 | 数值积分例程和微分方程求解器
30 |
31 | + scipy.linalg
32 |
33 | 线性代数例程和基于 numpy.linalg 的矩阵分解
34 |
35 | + scipy.optimize
36 |
37 | 函数优化器(最小化器)和求根算法
38 |
39 | + scipy.signal
40 |
41 | 信号处理工具
42 |
43 | + scipy.sparse
44 |
45 | 稀疏矩阵与稀疏线性系统求解器
46 |
47 | + scipy.special
48 |
49 | SPECFUN 的包装器。SPECFUN 是 Fortran 语言下实现的通用数据函数的包,例如 gamma 函数
50 |
51 | + scipy.stats
52 |
53 | 标准的连续和离散概率分布(密度函数、采样器、连续分布函数)、各类统计测试、各类描述性统计
54 |
55 | SciPy 和 NumPy 一起为很多传统科学计算应用提供了一个合理、完整、成熟的计算基础。
56 |
57 | ### scikit-learn
58 |
59 | scikit-learn 项目()诞生于 2010 年,目前已成为 Python 编程者首选的机器学习工具包。scikit-learn 包含以下子模块:
60 |
61 | + 分类:SVM、最近邻、随机森林、逻辑回归等
62 |
63 | + 回归:Lasso、岭回归等
64 |
65 | + 聚类:k-means、谱聚类等
66 |
67 | + 降维:PCA、特征选择、矩阵分解等
68 |
69 | + 模型选择:网格搜索、交叉验证、指标矩阵
70 |
71 | + 预处理:特征提取、正态化
72 |
73 | ### statsmodels
74 |
75 | statsmodels()是一个统计分析包,与 scikit-learn 相比,statsmodels 包含经典的(高频词汇)统计学、经济学算法。它包含的模型如下:
76 |
77 | + 回归模型:线性回归、通用线性模型、鲁棒线性模型、线性混合效应模型等
78 |
79 | + 方差分析(ANOVA)
80 |
81 | + 时间序列分析:AR、ARMA、ARIMA、VAR 等模型
82 |
83 | + 非参数方法:核密度估计、核回归
84 |
85 | + 统计模型结果可视化
--------------------------------------------------------------------------------
/step7-Data-Analysis/docs/02-IPython-and-Jupyter notebook.md:
--------------------------------------------------------------------------------
1 | ## 💬 IPython 及 Jupyter notebook
2 |
3 | ### 安装
4 |
5 | + IPython 的安装
6 |
7 | ```python
8 | pip install ipython
9 | ```
10 |
11 | + Jupyter 的安装
12 |
13 | ```python
14 | pip install jupyter
15 | ```
16 |
17 | ### 基本使用
18 |
19 | + IPython 的基本使用——启动
20 |
21 | ```bash
22 | # 终端中
23 | $ ipython
24 | d:\python3.9.0\lib\site-packages\IPython\core\interactiveshell.py:936: UserWarning: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
25 | warn("Attempting to work in a virtualenv. If you encounter problems, please "
26 | Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)]
27 | Type 'copyright', 'credits' or 'license' for more information
28 | IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.
29 |
30 | In [1]: a = 10
31 |
32 | In [2]: a
33 | Out[2]: 10
34 | ```
35 |
36 | + IPython 的基本使用——退出
37 |
38 | ```bash
39 | # 终端中
40 | ...
41 | In [1]: exit
42 | ```
43 |
44 | + Jupyter 的基本使用——启动
45 |
46 | ```bash
47 | # 终端中
48 | $ jupyter notebook
49 | ...
50 |
51 | # 通过地址 http://localhost:8888/ 来访问
52 | # Jupyter notebook 可以使用 IPython 命令
53 | ```
54 |
55 | + Jupyter 的基本使用——安装第三方包
56 |
57 | ```python
58 | # ipython 命令行中
59 | In [1]: ! pip install xxx
60 |
61 | # 如:! pip install matplotlib
62 | ```
63 |
64 | + Jupyter 的基本使用——退出
65 |
66 | ```bash
67 | # 终端中
68 |
69 | 快捷键 'ctrl + C' 退出
70 | ```
71 |
72 | ### IPython 基础
73 |
74 | > 可单独作用于终端或 Jupyter notebook 中
75 |
76 | + Tab 补全
77 |
78 | *变量名*
79 |
80 | ```python
81 | In [1]: an_apple = 27
82 |
83 | In [2]: an_example = 42
84 |
85 | In [3]: an
86 | an_apple an_example any
87 | ```
88 |
89 | *方法、属性*
90 |
91 | ```python
92 | In [1]: b = [1, 2, 3]
93 |
94 | In [2]: b.
95 | b.append b.count b.insert b.reverse
96 | b.clear b.extend b.pop b.sort
97 | b.copy b.index b.remove
98 | ```
99 |
100 | *模块*
101 |
102 | ```python
103 | In [1]: import datetime
104 |
105 | In [2]: datatime.
106 | datetime.date datetime.MAXYEAR datetime.timedelta
107 | datetime.datetime datetime.MINYEAR datetime.timezone
108 | datetime.datetime_CAPI datetime.time datetime.tzinfo
109 | ```
110 |
111 | *路径*
112 |
113 | ```python
114 | In [1]: datasets/movielens/
115 | datasets/movielens/movies,dat datasets/movielens/README
116 | datasets/movielens/ratings.dat datasets/movielens/users.dat
117 |
118 | In [2]: path = 'datasets/movielens/
119 | datasets/movielens/movies,dat datasets/movielens/README
120 | datasets/movielens/ratings.dat datasets/movielens/users.dat
121 | ```
122 |
123 | *关键字参数*
124 |
125 | ```python
126 | In [1]: def func_with_keywords(abra=1, abbra=2, abbbra=3):
127 | return abra, abbra, abbbra
128 |
129 | In [2]: func_with_keywords(ab)
130 | abbbra= abbra= abra= abs
131 | ```
132 |
133 | + 内省
134 |
135 | 在一个变量名的前后使用问号(?)可以显示一些关于该对象的概要信息,这就是对象内省:
136 |
137 | ```python
138 | In [1]: b = [1, 2, 3]
139 |
140 | In [2]: b?
141 | Type: list
142 | String form: [1, 2, 3]
143 | Length: 3
144 | Docstring:
145 | Built-in mutable sequence.
146 |
147 | If no argument is given, the constructor creates a new empty list.
148 | The argument must be an iterable if specified.
149 | ```
150 |
151 | 如果对象是一个函数或实例方法,则文档字符串会显示出来:
152 |
153 | ```python
154 | In [1]: def add_numbers(a, b):
155 | """
156 | Add two numbers together
157 |
158 | Returns
159 | -------
160 | the_sum : type of arguments
161 | """
162 | return a + b
163 |
164 | # 使用 ? 来显示文档字符串
165 | In [2]: add_numbers?
166 | Signature: add_numbers(a, b)
167 | Docstring:
168 | Add two numbers together
169 |
170 | Returns
171 | -------
172 | the_sum : type of arguments
173 | File: f:\2a.python数据分析\code\
174 | Type: function
175 |
176 | # 使用 ?? 来显示函数的源代码
177 | In [3]: add_numbers??
178 | Signature: add_numbers(a, b)
179 | Source:
180 | def add_numbers(a, b):
181 | """
182 | Add two numbers together
183 |
184 | Returns
185 | -------
186 | the_sum : type of arguments
187 | """
188 | return a + b
189 | File: f:\2a.python数据分析\code\
190 | Type: function
191 | ```
192 |
193 | 问号(?)可以结合星号(*)作为通配符匹配字符
194 |
195 | ```python
196 | In [1]: import datetime as dt
197 |
198 | In [2]: dt.*time*?
199 | dt.datetime
200 | dt.datetime_CAPI
201 | dt.time
202 | dt.timedelta
203 | dt.timezone
204 | ```
205 |
206 | + %run 命令
207 |
208 | 如果已有脚本文件 *ipython_script_test.py*:
209 |
210 | ```python
211 | def f(x, y, z):
212 | return (x + y) / z
213 |
214 | a = 5
215 | b = 6
216 | c = 7.5
217 |
218 |
219 | result = f(a, b, c)
220 | ```
221 |
222 | 则可以使用 %run 命令来运行,且运行后文件中定义的所有变量、函数均可任意使用:
223 |
224 | > 如果想使用 IPython 命名空间中已有的变量,则使用 **%run -i** 命令
225 |
226 | ```python
227 | In [1]: %run ipython_script_test.py
228 |
229 | In [2]: c
230 | Out[2]: 7.5
231 |
232 | In [3]: result
233 | Out[3]: 1.4666666666666666
234 |
235 | In [4]: f(1, 1, 2)
236 | Out[4]: 1.0
237 | ```
238 |
239 | 如果想把脚本导入一个代码单元,使用 %load 命令:
240 |
241 | ```python
242 | In [1]: %load ipython_script_test.py
243 | # %load ipython_script_test.py
244 | def f(x, y, z):
245 | return (x + y) / z
246 |
247 | a = 5
248 | b = 6
249 | c = 7.5
250 |
251 |
252 | result = f(a, b, c)
253 | ```
254 |
255 | + 魔术命令
256 |
257 | IPython 的特殊命令(没有内建到 Python 自身中去)被称为“魔术”命令,这些命令被设计来简化常见任务。魔术命令呃前缀符号是百分号 %,如查看当前路径:
258 |
259 | ```python
260 | In [1]: %pwd
261 | Out[1]: 'F:\\2a.Python数据分析\\code'
262 | ```
263 |
264 | 一些魔术命令可以赋值给 Python 变量:
265 |
266 | ```python
267 | In [1]: a = %pwd
268 |
269 | In [2]: a
270 | Out[2]: 'F:\\2a.Python数据分析\\code'
271 | ```
272 |
273 | 如果魔术命令与当前命名空间变量不冲突,则可不加 %,这种特性被称为 *自动魔术*,可使用 `%automagic` 进行启用或禁用:
274 |
275 | ```python
276 | In [1]: pwd
277 | Out[1]: 'F:\\2a.Python数据分析\\code'
278 |
279 | In [2]: %automagic
280 | Automagic is OFF, % prefix IS needed for line magics.
281 |
282 | In [3]: pwd
283 | ---------------------------------------------------------------------------
284 | NameError Traceback (most recent call last)
285 | F:\2a.Python数据分析\code\ipython_script_test.py in
286 | ----> 1 pwd
287 |
288 | NameError: name 'pwd' is not defined
289 | ```
290 |
291 | IPython 常用魔术命令:
292 |
293 | |命令|描述|
294 | |:--|:---|
295 | |%quickref|显示 IPython 快速参考卡|
296 | |%magic|显示所有可用魔术命令的详细文档|
297 | |%debug|从最后发生报错的底部进入交互式调试器|
298 | |%hist|打印命令输入(也可以打印输出)历史|
299 | |%pdb|出现任意报错后自动进入调试器|
300 | |%pwd|显示当前路径|
301 | |%reset|删除交互式命名空间中所有的变量/名称|
302 | |%page OBJECT|通过分页器更美观地打印显示一个对象|
303 | |%run script.py|在 IPython 中运行一个 Python 脚本|
304 | |%prun statement|使用 CProfile 执行语句,并报告输出|
305 | |%time statement|报告单个语句的执行时间|
306 | |%timeit statement|多次运行单个语句计算平均执行时间;在估算代码最短执行时间时有用|
307 | |%who, %who_ls, %whos|根据不同级别的信息/详细程度,展示交互命名空间中定义的变量|
308 | |%xdel variable|在 IPython 内部删除一个变量,消除相关的引用|
309 |
310 | + matplotlib 集成
311 |
312 | IPython 能在分析计算领域流行的原因之一,就是它和数据可视化、用户界面库(如 matplotlib)的良好集成。
313 |
314 | 注意,使用 matplotlib,要更换 numpy 版本:
315 |
316 | ```bash
317 | # 终端中
318 | pip install numpy==1.19.3
319 | ```
320 |
321 | 要在 Jupyter 网页外显示图(后台),使用魔术命令 %matplotlib:
322 |
323 | ```python
324 | In [1]: %matplotlib
325 | Using matplotlib backend: TkAgg
326 |
327 | In [2]: import matplotlib.pyplot as plt
328 |
329 | In [3]: import numpy as np
330 |
331 | In [4]: plt.plot(np.random.randn(50).cumsum())
332 | []
333 | ```
334 |
335 | 要在 Jupyter 网页内显示图,使用魔术命令 %matplotlib inline:
336 |
337 | ```python
338 | In [1]: %matplotlib inline
339 |
340 | In [2]: import matplotlib.pyplot as plt
341 |
342 | In [3]: import numpy as np
343 |
344 | In [4]: plt.plot(np.random.randn(50).cumsum())
345 | []
346 | ```
347 |
--------------------------------------------------------------------------------
/step7-Data-Analysis/docs/03-Python-base.md:
--------------------------------------------------------------------------------
1 | ## 💬 Python 语言基础
2 |
3 | ### 语言语义
4 |
5 | + Tab(或空格) 缩进
6 |
7 | ```python
8 | for x in array:
9 | if x < pivot:
10 | less.append(x)
11 | else:
12 | greater.append(x)
13 | ```
14 |
15 | + 一切皆对象
16 |
17 | 每一个数值、字符串、数据结构、函数、类、模块以及所有存在于 Python 解释器中的事物,都是 Python 对象。
18 |
19 | + 注释
20 |
21 | 当行注释
22 |
23 | ```python
24 | # 此行被注释
25 |
26 | print("Hello World") # 当然也可以注释在语句后
27 | ```
28 |
29 | 多行注释
30 |
31 | ```python
32 | '''
33 | 多行注释,使用三个单引号 '
34 | '''
35 |
36 | """
37 | 多行注释,也可使用三个双引号 "
38 | """
39 |
40 | """
41 | 当然,单引号和双引号不能混用!
42 | '''
43 | ```
44 |
45 | + 函数和对象方法的调用
46 |
47 | 调用函数,向函数括号里传递 0 或多个参数,通常会把返回值赋值给一个变量:
48 |
49 | ```python
50 | result = f(x, y, z)
51 | g()
52 | ```
53 |
54 | 调用对象内部方法,使用点:
55 |
56 | ```python
57 | obj.some_method(x, y, z)
58 |
59 | # 函数传参既可以是位置参数也可以是关键字参数:
60 | result = f(a, b, c, d=5, e='foo')
61 | ```
62 |
63 | + 变量和参数传递
64 |
65 | Python 中,对变量赋值时,你就创建了一个指向等号右边对象的引用,例如:
66 |
67 | ```python
68 | # 变量 a,赋值一个列表 list
69 | a = [1, 2, 3]
70 |
71 | # 现将 a 赋值给新变量 b
72 | b = a
73 |
74 | '''
75 | 某些语言中,这种赋值是值拷贝过程,即上述中是列表 [1,2,3] 赋值给了 b
76 | 而在 Python 中,是 a、b 指向了相同的对象 list[1,2,3]
77 | 可以验证如下:
78 | '''
79 | b.append(4)
80 |
81 | print(a)
82 | # 输出 [1, 2, 3, 4]
83 | ```
84 |
85 | Python 中有 *可更改(mutable)对象* 与 *不可更改(immutable)对象*。可更改类型有:list、dict;不可更改类型有:string、tuple、number
86 |
87 | 在函数参数传递中,对于可更改对象,类似于 C++ 引用传递,对于不可更改类型,类似于 C++ 值传递:
88 |
89 | ```python
90 | # 不可更改对象作为函数参数
91 | def f1(value):
92 | value += 1
93 |
94 | a = 10
95 | f1(a)
96 | print(a) # 输出 10
97 |
98 |
99 | # 可更改对象作为函数参数
100 | def f2(some_list, element):
101 | some_list.append(element)
102 |
103 | data = [1, 2, 3]
104 | f2(data, 4)
105 | print(data) # 输出 [1, 2, 3, 4]
106 | ```
107 |
108 | + 动态引用、强类型
109 |
110 | Python 中的对象引用并不涉及类型,这称为 *动态类型*:
111 |
112 | ```python
113 | a = 5
114 | pring(type(a)) # int
115 |
116 | a = 'foo'
117 | print(type(a)) # str
118 | ```
119 |
120 | Python 是 *强类型语言*,这意味着所有的对象都拥有一个指定的类型(或类),隐式转换只在某些特定、明显的情况下发生:
121 |
122 | ```python
123 | print('5' + 5)
124 | ---------------------------------------------------------------------------
125 | TypeError Traceback (most recent call last)
126 | in
127 | ----> 1 '5' + 5
128 |
129 | TypeError: can only concatenate str (not "int") to str
130 | ```
131 |
132 | ```python
133 | a = 4.5
134 | b = 2
135 |
136 | print('a is {0}, b is {1}'.format(type(a), type(b)))
137 | # 输出 a is , b is
138 | print(a / b)
139 | # 输出 2.25
140 | print(type(a / b))
141 | # 输出
142 | ```
143 |
144 | *isinstance* 函数可以检查一个对象是否是特定类型的实例:
145 |
146 | ```python
147 | a = 5
148 | print(isinstance(a, int))
149 | # 输出 True
150 |
151 | # 也可以接收一个元组,判断 对象 是否是其中类型之一
152 | b = 4.5
153 | print(isinstance(a, (int, float)))
154 | # 输出 True
155 | print(isinstance(b, (int, float)))
156 | # 输出 True
157 | ```
158 |
159 | + 属性和方法
160 |
161 | Python 中对象通常都会有属性和方法,属性和方法都可以通过 `obj.attribute_name` 调用:
162 |
163 | ```python
164 | In [1]: a = 'foo'
165 |
166 | In [2]: a.
167 | a.capitalize a.format ...
168 | ```
169 |
170 | 属性和方法也可通过 *getattr* 函数获得,这种通过变量名访问对象通常被称为“反射”:
171 |
172 | ```python
173 | getattr(a, 'split')
174 | #
175 |
176 | # 同类型还有 hasattr 和 setattr
177 | ```
178 |
179 | + 鸭子类型
180 |
181 | 通常情况下,你并不关心某个对象的具体类型,而关心它是否拥有某个特殊的方法或行为。
182 |
183 | > “鸭子类型” 说法源于 “一个东西走起来像鸭子叫起来像鸭子,那它就是鸭子”。例如,你可以验证一个对象如果实现了迭代器协议,那么它一定是可迭代的(包含 \_\_iter\_\_ 魔术方法)
184 |
185 | ```python
186 | def isiterable(obj):
187 | try:
188 | iter(obj)
189 | return True
190 | except TypeError:
191 | return False
192 |
193 | # 对于绝大部分 Python 容器类型的对象,iter 函数都会返回 True
194 | isiterable('a string')
195 | # True
196 | isiterable([1, 2, 3])
197 | # True
198 | isiterable(5)
199 | # False
200 |
201 | # 常见的案例是先检查对象是否是一个列表(或一个 NumPy 数组)
202 | # 如果不是则转换为一个列表
203 | if not isinstance(x, list) and isiterable(x):
204 | x = list(x)
205 | ```
206 |
207 | + 导入模块
208 |
209 | Python 模块就是以 *.py* 为后缀并包含 Python 代码的文件。假设有以下模块:
210 |
211 | ```python
212 | # some_module.py
213 | PI = 3.14159
214 |
215 | def f(x):
216 | return x + 2
217 |
218 | def g(a, b):
219 | return a + b
220 | ```
221 |
222 | 要导入模块中定义的变量和函数:
223 |
224 | ```python
225 | import some_module
226 |
227 | result = some_module.f(5)
228 | pi = some_module.PI
229 | ```
230 |
231 | 或者:
232 |
233 | ```python
234 | from some_module import f, g, PI
235 |
236 | result = g(5, PI)
237 | ```
238 |
239 | 也可用关键字 as,对导入内容更名:
240 |
241 | ```python
242 | import some_module as sm
243 | from some_module import PI as pi, g as gf
244 |
245 | r1 = sm.f(pi)
246 | r2 = gf(6, pi)
247 | ```
248 |
249 |
250 | 上述为 Python 中的一些基本特性,语法中的其他内容后续补充。
--------------------------------------------------------------------------------
/step7-Data-Analysis/docs/04-Python-advanced.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step7-Data-Analysis/docs/04-Python-advanced.md
--------------------------------------------------------------------------------
/step7-Data-Analysis/docs/numpy 模块/README.md:
--------------------------------------------------------------------------------
1 | ## numpy 模块
2 |
3 | Numpy(Numerical Python)是 Python 中做科学计算的基础库。重在数值运算,也是大部分 Python 科学计算库的基础,多用于在大型、多维数组上执行的数值运算。
4 |
5 | + 安装:
6 |
7 | ```python
8 | pip install numpy
9 | ```
10 |
11 | ### numpy 的创建
12 |
13 | + 使用 `np.array()` 创建:
14 |
15 | ```python
16 | import numpy as np
17 |
18 | # 创建一维数组
19 | arr1 = np.array([1, 2, 3, 4, 5])
20 | # 创建二维数组
21 | arr2 = np.array([1, 2, 3], [4, 5, 6])
22 | ```
23 |
24 | + 数组和列表区别:数组中存储的数据元素类型必须一致
25 |
26 | + 使用 `plt` 创建:
27 |
28 | ```python
29 | import matplotlib.pyplot as plt
30 |
31 | # 图片数据的读取(三维数组)
32 | img_arr = plt.imread('./demo.jpg')
33 |
34 | # 将一个三维的 numpy 数组显示成一张图片
35 | plt.imshow(img_arr)
36 | ```
--------------------------------------------------------------------------------
/step8-Machine-Learning/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fmw666/Python/3372ba92c59803fb5e97b936be1b74166ed688a1/step8-Machine-Learning/README.md
--------------------------------------------------------------------------------