Merge pull request #1 from jackfrued/master

更新
pull/277/head
austinyu2019 2019-08-12 11:08:25 +08:00 committed by GitHub
commit dd3ddfa813
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
516 changed files with 95308 additions and 7181 deletions

11
.gitignore vendored
View File

@ -3,3 +3,14 @@ venv
*.pyc *.pyc
__pycache__ __pycache__
### VisualStudioCode ###
.vscode/*
.vscode/**
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### VisualStudioCode Patch ###
# Ignore all local history of files
.history

View File

@ -1,16 +1,16 @@
## Day01 - 初识Python ## 初识Python
### Python简介 ### Python简介
#### Python的历史 #### Python的历史
1. 1989年圣诞节Guido von Rossum开始写Python语言的编译器。 1. 1989年圣诞节Guido von Rossum开始写Python语言的编译器。
2. 1991年2月第一个Python编译器同时也是解释器诞生它是用C语言实现的后面又出现了Java和C#实现的版本Jython和IronPython以及PyPy、Brython、Pyston等其他实现可以调用C语言的库函数。在最早的版本中Python已经提供了对“类”“函数”“异常处理”等构造块的支持同时提供了“列表”和“字典”等核心数据类型同时支持以模块为基础的拓展系统 2. 1991年2月第一个Python编译器同时也是解释器诞生它是用C语言实现的后面又出现了Java和C#实现的版本Jython和IronPython以及PyPy、Brython、Pyston等其他实现可以调用C语言的库函数。在最早的版本中Python已经提供了对“类”“函数”“异常处理”等构造块的支持同时提供了“列表”和“字典”等核心数据类型同时支持以模块为基础来构造应用程序
3. 1994年1月Python 1.0正式发布。 3. 1994年1月Python 1.0正式发布。
4. 2000年10月16日Python 2.0发布,增加了实现完整的[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8)),提供了对[Unicode](https://zh.wikipedia.org/wiki/Unicode)的支持。与此同时Python的整个开发过程更加透明社区对开发进度的影响逐渐扩大生态圈开始慢慢形成。 4. 2000年10月16日Python 2.0发布,增加了实现完整的[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8)),提供了对[Unicode](https://zh.wikipedia.org/wiki/Unicode)的支持。与此同时Python的整个开发过程更加透明社区对开发进度的影响逐渐扩大生态圈开始慢慢形成。
5. 2008年12月3日Python 3.0发布它并不完全兼容之前的Python代码不过因为目前还有不少公司在项目和运维中使用Python 2.x版本所以Python 3.x的很多新特性后来也被移植到Python 2.6/2.7版本中。 5. 2008年12月3日Python 3.0发布它并不完全兼容之前的Python代码不过因为目前还有不少公司在项目和运维中使用Python 2.x版本所以Python 3.x的很多新特性后来也被移植到Python 2.6/2.7版本中。
目前我们使用的Python 3.7.x的版本是在2018年发布的Python的版本号分为三段形如A.B.C。其中A表示大版本号一般当整体重写或出现不向后兼容的改变时增加AB表示功能更新出现新功能时增加BC表示小的改动如修复了某个Bug只要有修改就增加C。如果对Python的历史感兴趣可以查看一篇名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的博文。 目前我们使用的Python 3.7.x的版本是在2018年发布的Python的版本号分为三段形如A.B.C。其中A表示大版本号一般当整体重写或出现不向后兼容的改变时增加AB表示功能更新出现新功能时增加BC表示小的改动修复了某个Bug只要有修改就增加C。如果对Python的历史感兴趣可以阅读名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的博文。
#### Python的优缺点 #### Python的优缺点
@ -27,18 +27,20 @@ Python的优点很多简单的可以总结为以下几点。
Python的缺点主要集中在以下几点。 Python的缺点主要集中在以下几点。
1. 执行效率稍低因此计算密集型任务可以由C/C++编写。 1. 执行效率稍低因此计算密集型任务可以由C/C++编写。
2. 代码无法加密,但是现在的公司很多都不是卖软件而是卖服务,这个问题会被淡化。 2. 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被淡化。
3. 在开发时可以选择的框架太多如Web框架就有100多个有选择的地方就有错误。 3. 在开发时可以选择的框架太多如Web框架就有100多个有选择的地方就有错误。
#### Python的应用领域 #### Python的应用领域
目前Python在云基础设施、DevOps、网络爬虫开发、数据分析挖掘、机器学习等领域都有着广泛的应用因此也产生了Web后端开发、数据接口开发、自动化运维、自动化测试、科学计算和可视化、数据分析、量化交易、机器人开发、图像识别和处理等一系列的职位。 目前Python在Web应用开发、云基础设施、DevOps、网络爬虫开发、数据分析挖掘、机器学习等领域都有着广泛的应用因此也产生了Web后端开发、数据接口开发、自动化运维、自动化测试、科学计算和可视化、数据分析、量化交易、机器人开发、图像识别和处理等一系列的职位。
### 搭建编程环境 ### 搭建编程环境
#### Windows环境 #### Windows环境
可以在[Python官方网站](https://www.python.org)下载到Python的Windows安装程序exe文件需要注意的是如果在Windows 7环境下安装需要先安装Service Pack 1补丁包可以通过一些工具软件自动安装系统补丁的功能来安装安装过程建议勾选“Add Python 3.6 to PATH”将Python 3.6添加到PATH环境变量并选择自定义安装在设置“Optional Features”界面最好将“pip”、“tcl/tk”、“Python test suite”等项全部勾选上。强烈建议使用自定义的安装路径并保证路径中没有中文。安装完成会看到“Setup was successful”的提示但是在启动Python环境时可能会因为缺失一些动态链接库文件而导致Python解释器无法运行常见的问题主要是api-ms-win-crt\*.dll缺失以及更新DirectX之后导致某些动态链接库文件缺失前者可以参照[《api-ms-win-crt\*.dll缺失原因分析和解决方法》]()一文讲解的方法进行处理或者直接在[微软官网](https://www.microsoft.com/zh-cn/download/details.aspx?id=48145)下载Visual C++ Redistributable for Visual Studio 2015文件进行修复后者可以下载一个DirectX修复工具进行修复。 可以在[Python官方网站](https://www.python.org)下载到Python的Windows安装程序exe文件需要注意的是如果在Windows 7环境下安装Python 3.x需要先安装Service Pack 1补丁包可以通过一些工具软件自动安装系统补丁的功能来安装安装过程建议勾选“Add Python 3.x to PATH”将Python 3.x添加到PATH环境变量并选择自定义安装在设置“Optional Features”界面最好将“pip”、“tcl/tk”、“Python test suite”等项全部勾选上。强烈建议选择自定义的安装路径并保证路径中没有中文。安装完成会看到“Setup was successful”的提示。如果稍后运行Python程序时出现因为缺失一些动态链接库文件而导致Python解释器无法工作的问题可以按照下面的方法加以解决。
如果系统显示api-ms-win-crt\*.dll文件缺失可以参照[《api-ms-win-crt\*.dll缺失原因分析和解决方法》](<https://zhuanlan.zhihu.com/p/32087135>)一文讲解的方法进行处理或者直接在[微软官网](https://www.microsoft.com/zh-cn/download/details.aspx?id=48145)下载Visual C++ Redistributable for Visual Studio 2015文件进行修复如果是因为更新Windows的DirectX之后导致某些动态链接库文件缺失问题可以下载一个[DirectX修复工具](<https://dl.pconline.com.cn/download/360074-1.html>)进行修复。
#### Linux环境 #### Linux环境
@ -81,24 +83,32 @@ export PATH=$PATH:/usr/local/python37/bin
# ... 此处省略下面的代码 ... # ... 此处省略下面的代码 ...
``` ```
激活环境变量。
```Shell ```Shell
source .bash_profile source .bash_profile
``` ```
#### MacOS环境 #### macOS环境
MacOS也是自带了Python 2.x版本的,可以通过[Python的官方网站](https://www.python.org)提供的安装文件pkg文件安装3.x的版本。默认安装完成后可以通过在终端执行python命令来启动2.x版本的Python解释器可以通过执行python3命令来启动3.x版本的Python解释器。 macOS也自带了Python 2.x版本,可以通过[Python的官方网站](https://www.python.org)提供的安装文件pkg文件安装Python 3.x的版本。默认安装完成后可以通过在终端执行python命令来启动2.x版本的Python解释器可以通过执行python3命令来启动3.x版本的Python解释器。
### 从终端运行Python程序 ### 从终端运行Python程序
#### 确认Python的版本 #### 确认Python的版本
在终端或命令行提示符中键入下面的命令。 可以Windows的命令行提示符中键入下面的命令。
```Shell ```Shell
python --version python --version
``` ```
当然也可以先输入python进入交互式环境再执行以下的代码检查Python的版本。 或者是在Linux或macOS系统的终端中键入下面的命令。
```Shell
python3 --version
```
当然也可以先输入python或python3进入交互式环境再执行以下的代码检查Python的版本。
```Python ```Python
import sys import sys
@ -109,7 +119,7 @@ print(sys.version)
#### 编写Python源代码 #### 编写Python源代码
可以用文本编辑工具(推荐使用Sublime、Atom、TextMate、VSCode等高级文本编辑工具编写Python源代码并将其命名为hello.py保存起来,代码内容如下所示。 可以用文本编辑工具(推荐使用[Sublime](<https://www.sublimetext.com/>)、[Atom](<https://atom.io/>)、[Visual Studio Code](<https://code.visualstudio.com/>)等高级文本编辑工具编写Python源代码并用py作为后缀名保存该文件,代码内容如下所示。
```Python ```Python
print('hello, world!') print('hello, world!')
@ -123,6 +133,12 @@ print('hello, world!')
python hello.py python hello.py
``` ```
```Shell
python3 hello.py
```
### 代码中的注释 ### 代码中的注释
注释是编程语言的一个重要组成部分,用于在源代码中解释代码的作用从而增强程序的可读性和可维护性,当然也可以将源代码中不需要参与运行的代码段通过注释来去掉,这一点在调试程序的时候经常用到。注释在随源代码进入预处理器或编译时会被移除,不会在目标代码中保留也不会影响程序的执行结果。 注释是编程语言的一个重要组成部分,用于在源代码中解释代码的作用从而增强程序的可读性和可维护性,当然也可以将源代码中不需要参与运行的代码段通过注释来去掉,这一点在调试程序的时候经常用到。注释在随源代码进入预处理器或编译时会被移除,不会在目标代码中保留也不会影响程序的执行结果。
@ -156,56 +172,67 @@ IDLE是安装Python环境时自带的集成开发工具如下图所示。但
#### IPython - 更好的交互式编程工具 #### IPython - 更好的交互式编程工具
IPython是一种基于Python的交互式解释器。相较于原生的Python ShellIPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython和Jupyter具体的操作如下所示。 IPython是一种基于Python的交互式解释器。相较于原生的Python交互式环境IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython和Jupyter具体的操作如下所示。
```Shell ```Shell
pip install ipython jupyter pip install ipython
``` ```
```Shell ```Shell
python -m pip install ipython jupyter pip3 install ipython
``` ```
安装成功后可以通过下面的ipython命令启动IPython如下图所示。 安装成功后可以通过下面的ipython命令启动IPython如下图所示。
![](./res/python-ipython.png) ![](./res/python-ipython.png)
当然我们也可以通过Jupyter运行名为notebook的项目在浏览器窗口中进行交互式操作。 当然我们也可以通过安装Jupyter工具并运行名为notebook的程序在浏览器窗口中进行交互式代码编写操作。
```Shell
pip install jupyter
```
```Shell
pip3 intall jupyter
```
然后执行下面的命令:
```Shell ```Shell
jupyter notebook jupyter notebook
``` ```
![](./res/python-jupyter-2.png) ![](./res/python-jupyter-2.png)
#### anaconda - 一站式的数据科学神器 #### Sublime / Visual Studio Code - 高级文本编辑器
Anaconda指的是一个开源的Python发行版本其包含了conda、Python等180多个科学包及其依赖项。
因为包含了大量的科学包Anaconda 的下载文件比较大(约 531 MB如果只需要某些包或者需要节省带宽或存储空间也可以使用Miniconda这个较小的发行版仅包含conda和 Python
对于学习数据科学的人来说anaconda是绝对的神器安装简便而且anaconda支持安装相关软件【例如前文提到的ipythonjupyter notebook甚至有R等其他数据科学软件 】
[一个相当有价值的介绍](https://www.jianshu.com/p/169403f7e40c)
现在唯一的问题在于清华镜像服务已经关闭,跨国下载会比较慢
#### Sublime - 文本编辑神器
![](./res/python-sublime.png) ![](./res/python-sublime.png)
- 首先可以通过[官方网站](https://www.sublimetext.com/)下载安装程序安装Sublime 3或Sublime 2。 - 首先可以通过[官方网站](https://www.sublimetext.com/)下载安装程序安装Sublime 3或Sublime 2。
- 安装包管理工具。通过快捷键Ctrl+`或者在View菜单中选择Show Console打开控制台输入下面的代码。 - 安装包管理工具。
1. 通过快捷键Ctrl+`或者在View菜单中选择Show Console打开控制台输入下面的代码。
- Sublime 3 - Sublime 3
```Python ```Python
import urllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read()) import urllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())
``` ```
- Sublime 2 - Sublime 2
```Python ```Python
import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation') import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation')
``` ```
2. 手动安装浏览器输入 https://sublime.wbond.net/Package%20Control.sublime-package 下载这个文件
下载好以后打开sublime text选择菜单Preferences->Browse Packages... 打开安装目录
此时会进入到一个叫做Packages的目录下点击进入上一层目录Sublime Text3在此目录下有一个文件夹叫做Installed Packages把刚才下载的文件放到这里就可以了。然后重启sublime text3观察Preferences菜单最下边是否有Package Settings 和Package Control两个选项如果有则代表安装成功了。
- 安装插件。通过Preference菜单的Package Control或快捷键Ctrl+Shift+P打开命令面板在面板中输入Install Package就可以找到安装插件的工具然后再查找需要的插件。我们推荐大家安装以下几个插件 - 安装插件。通过Preference菜单的Package Control或快捷键Ctrl+Shift+P打开命令面板在面板中输入Install Package就可以找到安装插件的工具然后再查找需要的插件。我们推荐大家安装以下几个插件
@ -215,42 +242,29 @@ Anaconda指的是一个开源的Python发行版本其包含了conda、Python
- Python PEP8 Autoformat - PEP8规范自动格式化插件。 - Python PEP8 Autoformat - PEP8规范自动格式化插件。
- ConvertToUTF8 - 将本地编码转换为UTF-8。 - ConvertToUTF8 - 将本地编码转换为UTF-8。
> 说明事实上Visual Studio Code可能是更好的选择它不用花钱并提供了更为完整和强大的功能有兴趣的读者可以自行研究。
#### PyCharm - Python开发神器 #### PyCharm - Python开发神器
PyCharm的安装、配置和使用我们在后面会进行介绍 PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)进行了介绍,有兴趣的读者可以选择阅读
![](./res/python-pycharm.png) ![](./res/python-pycharm.png)
### 练习 ### 练习
1. 在Python交互环境中查看下面的代码结果并将内容翻译成中文。 1. 在Python交互环境中查看下面的代码结果试着这些内容翻译成中文。
```Python ```Python
import this import this
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
``` ```
> 说明当前键入上面的命令后会在交互式环境中看到如下所示的输出这段内容被称为“Python之禅”里面讲述的道理不仅仅适用于Python也适用于其他编程语言。
>
2. 学习使用turtle在屏幕上绘制图形。 2. 学习使用turtle在屏幕上绘制图形。
> 说明turtle是Python内置的一个非常有趣的模块特别适用于让小朋友体会什么是编程它最早是Logo语言的一部分Logo语言是Wally Feurzig和Seymour Papert在1966发明的编程语言.
```Python ```Python
import turtle import turtle

View File

@ -1,12 +1,14 @@
## Day02 - 语言元素 ## 语言元素
#### 指令和程序 #### 指令和程序
计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们使用的计算机虽然器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的计算机。“冯·诺依曼结构”有两个关键点一是指出要将存储设备与中央处理器分开二是提出了将数据以二进制方式编码。二进制是一种“逢二进一”的计数法跟我们人类使用的“逢十进一”的计数法没有实质性的区别人类因为有十根手指所以使用了十进制因为在数数时十根手指用完之后就只能进位了当然凡事都有例外玛雅人可能是因为长年光着脚的原因把脚趾头也算上了于是他们使用了二十进制的计数法在这种计数法的指导下玛雅人的历法就与我们平常使用的历法不一样而按照玛雅人的历法2012年是上一个所谓的“太阳纪”的最后一年而2013年则是新的“太阳纪”的开始后来这件事情被以讹传讹的方式误传为”2012年是玛雅人预言的世界末日“这种荒诞的说法今天我们可以大胆的猜测玛雅文明之所以发展缓慢估计也与使用了二十进制有关。对于计算机来说二进制在物理器件上来说是最容易实现的高电压表示1低电压表示0于是在“冯·诺依曼结构”的计算机都使用了二进制。虽然我们并不需要每个程序员都能够使用二进制的思维方式来工作但是了解二进制以及它与我们生活中的十进制之间的转换关系以及二进制与八进制和十六进制的转换关系还是有必要的。如果你对这一点不熟悉可以自行使用[维基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[百度百科](https://baike.baidu.com)科普一下。 计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们大多数时候使用的计算机,虽然它们的元器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的计算机。“冯·诺依曼结构”有两个关键点一是指出要将存储设备与中央处理器分开二是提出了将数据以二进制方式编码。二进制是一种“逢二进一”的计数法跟我们人类使用的“逢十进一”的计数法没有实质性的区别人类因为有十根手指所以使用了十进制因为在数数时十根手指用完之后就只能进位了当然凡事都有例外玛雅人可能是因为长年光着脚的原因把脚趾头也算上了于是他们使用了二十进制的计数法在这种计数法的指导下玛雅人的历法就与我们平常使用的历法不一样而按照玛雅人的历法2012年是上一个所谓的“太阳纪”的最后一年而2013年则是新的“太阳纪”的开始后来这件事情被以讹传讹的方式误传为”2012年是玛雅人预言的世界末日“这种荒诞的说法今天我们可以大胆的猜测玛雅文明之所以发展缓慢估计也与使用了二十进制有关。对于计算机来说二进制在物理器件上来说是最容易实现的高电压表示1低电压表示0于是在“冯·诺依曼结构”的计算机都使用了二进制。虽然我们并不需要每个程序员都能够使用二进制的思维方式来工作但是了解二进制以及它与我们生活中的十进制之间的转换关系以及二进制与八进制和十六进制的转换关系还是有必要的。如果你对这一点不熟悉可以自行使用[维基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[百度百科](https://baike.baidu.com)科普一下。
> 提示:近期关于**量子计算机**的研究已经被推倒了风口浪尖量子计算机基于量子力学进行运算使用量子瞬移的方式来传递信息。2018年6月Intel宣布开发出新款量子芯片并通过了在接近绝对零度环境下的测试2019年1月IBM向全世界发布了首款商业化量子计算机。
### 变量和类型 ### 变量和类型
在程序设计中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取和修改,这是所有计算和控制的基础。计算机能处理的数据有很多类型除了数值之外还可以处理文本、图形、音频、视频等各种各样的数据那么不同的数据就需要定义不同的存储类型。Python中的数据类型很多而且也允许我们自定义新的数据类型这一点在后面会讲到我们先介绍几种常用的数据类型。 在程序设计中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取和修改,这是所有计算和控制的基础。计算机能处理的数据有很多类型除了数值之外还可以处理文本、图形、音频、视频等各种各样的数据那么不同的数据就需要定义不同的存储类型。Python中的数据类型很多而且也允许我们自定义新的数据类型这一点在后面会讲到我们先介绍几种常用的数据类型。
- 整型Python中可以处理任意大小的整数Python 2.x中有int和long两种类型的整数但这种区分对Python来说意义不大因此在Python 3.x中整数只有int这一种了而且支持二进制如`0b100`换算成十进制是4、八进制如`0o100`换算成十进制是64、十进制`100`)和十六进制(`0x100`换算成十进制是256的表示法。 - 整型Python中可以处理任意大小的整数Python 2.x中有int和long两种类型的整数但这种区分对Python来说意义不大因此在Python 3.x中整数只有int这一种了而且支持二进制如`0b100`换算成十进制是4、八进制如`0o100`换算成十进制是64、十进制`100`)和十六进制(`0x100`换算成十进制是256的表示法。
- 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。 - 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。
@ -50,12 +52,11 @@ print(a / b)
print(a // b) print(a // b)
print(a % b) print(a % b)
print(a ** b) print(a ** b)
``` ```
```Python ```Python
""" """
使用input函数输入 使用input()函数获取键盘输入
使用int()进行类型转换 使用int()进行类型转换
用占位符格式化输出的字符串 用占位符格式化输出的字符串
@ -72,7 +73,6 @@ print('%d / %d = %f' % (a, b, a / b))
print('%d // %d = %d' % (a, b, a // b)) print('%d // %d = %d' % (a, b, a // b))
print('%d %% %d = %d' % (a, b, a % b)) print('%d %% %d = %d' % (a, b, a % b))
print('%d ** %d = %d' % (a, b, a ** b)) print('%d ** %d = %d' % (a, b, a ** b))
``` ```
```Python ```Python
@ -94,16 +94,15 @@ print(type(b))
print(type(c)) print(type(c))
print(type(d)) print(type(d))
print(type(e)) print(type(e))
``` ```
在对变量类型进行转换时可以使用Python的内置函数准确的说下面列出的并不是真正意义上的函数而是后面我们要讲到的创建对象的构造方法 在对变量类型进行转换时可以使用Python的内置函数准确的说下面列出的并不是真正意义上的函数而是后面我们要讲到的创建对象的构造方法
- int():将一个数值或字符串转换成整数,可以指定进制。 - `int()`:将一个数值或字符串转换成整数,可以指定进制。
- float():将一个字符串转换成浮点数。 - `float()`:将一个字符串转换成浮点数。
- str():将指定的对象转换成字符串形式,可以指定编码。 - `str()`:将指定的对象转换成字符串形式,可以指定编码。
- chr():将整数转换成该编码对应的字符串(一个字符)。 - `chr()`:将整数转换成该编码对应的字符串(一个字符)。
- ord():将字符串(一个字符)转换成对应的编码(整数)。 - `ord()`:将字符串(一个字符)转换成对应的编码(整数)。
### 运算符 ### 运算符
@ -118,7 +117,7 @@ Python支持多种运算符下表大致按照优先级从高到低的顺序
| `+` `-` | 加,减 | | `+` `-` | 加,减 |
| `>>` `<<` | 右移,左移 | | `>>` `<<` | 右移,左移 |
| `&` | 按位与 | | `&` | 按位与 |
| `^` `|` | 按位异或,按位或 | | `^` `\|` | 按位异或,按位或 |
| `<=` `<` `>` `>=` | 小于等于,小于,大于,大于等于 | | `<=` `<` `>` `>=` | 小于等于,小于,大于,大于等于 |
| `==` `!=` | 等于,不等于 | | `==` `!=` | 等于,不等于 |
| `is` `is not` | 身份运算符 | | `is` `is not` | 身份运算符 |
@ -126,7 +125,7 @@ Python支持多种运算符下表大致按照优先级从高到低的顺序
| `not` `or` `and` | 逻辑运算符 | | `not` `or` `and` | 逻辑运算符 |
| `=` `+=` `-=` `*=` `/=` `%=` `//=` `**=` `&=` `|=` `^=` `>>=` `<<=` | (复合)赋值运算符 | | `=` `+=` `-=` `*=` `/=` `%=` `//=` `**=` `&=` `|=` `^=` `>>=` `<<=` | (复合)赋值运算符 |
>**说明:**在实际开发中,如果搞不清楚优先级可以使用括号来确保运算的执行顺序。 >**说明:** 在实际开发中,如果搞不清楚运算符的优先级可以使用括号来确保运算的执行顺序。
下面的例子演示了运算符的使用。 下面的例子演示了运算符的使用。
@ -161,7 +160,6 @@ print("flag4 = ", flag4)
print("flag5 = ", flag5) print("flag5 = ", flag5)
print(flag1 is True) print(flag1 is True)
print(flag2 is not False) print(flag2 is not False)
``` ```
### 练习 ### 练习
@ -180,7 +178,6 @@ Author: 骆昊
f = float(input('请输入华氏温度: ')) f = float(input('请输入华氏温度: '))
c = (f - 32) / 1.8 c = (f - 32) / 1.8
print('%.1f华氏度 = %.1f摄氏度' % (f, c)) print('%.1f华氏度 = %.1f摄氏度' % (f, c))
``` ```
#### 练习2输入圆的半径计算计算周长和面积。 #### 练习2输入圆的半径计算计算周长和面积。
@ -200,7 +197,6 @@ perimeter = 2 * math.pi * radius
area = math.pi * radius * radius area = math.pi * radius * radius
print('周长: %.2f' % perimeter) print('周长: %.2f' % perimeter)
print('面积: %.2f' % area) print('面积: %.2f' % area)
``` ```
#### 练习3输入年份判断是不是闰年。 #### 练习3输入年份判断是不是闰年。

View File

@ -1,12 +1,12 @@
## Day03 - 分支结构 ## 分支结构
### 分支结构的应用场景 ### 应用场景
迄今为止我们写的Python代码都是一条一条语句顺序执行这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所有的问题比如我们设计一个游戏游戏第一关的通关条件是玩家获得1000分那么在完成本局游戏后我们要根据玩家得到分数来决定究竟是进入第二关还是告诉玩家“Game Over”这里就会产生两个分支而且这两个分支只有一个会被执行,这就是程序中分支结构。类似的场景还有很多给大家一分钟的时间你应该可以想到至少5个以上这样的例子赶紧试一试。 迄今为止我们写的Python代码都是一条一条语句顺序执行这种代码结构通常称之为顺序结构。然而仅有顺序结构并不能解决所有的问题比如我们设计一个游戏游戏第一关的通关条件是玩家获得1000分那么在完成本局游戏后我们要根据玩家得到分数来决定究竟是进入第二关还是告诉玩家“Game Over”这里就会产生两个分支而且这两个分支只有一个会被执行。类似的场景还有很多我们将这种结构称之为“分支结构”或“选择结构”。给大家一分钟的时间你应该可以想到至少5个以上这样的例子赶紧试一试。
### if语句的使用 ### if语句的使用
在Python中要构造分支结构可以使用`if`、`elif`和`else`关键字。所谓关键字就是有特殊含义的单词,像`if`和`else`就是专门用于构造分支结构的关键字,很显然你不能够使用它作为变量名(事实上,用作其他的标识符也是不可以)。下面的例子中演示了如何构造一个分支结构。 在Python中要构造分支结构可以使用`if`、`elif`和`else`关键字。所谓**关键字**就是有特殊含义的单词,像`if`和`else`就是专门用于构造分支结构的关键字,很显然你不能够使用它作为变量名(事实上,用作其他的标识符也是不可以)。下面的例子中演示了如何构造一个分支结构。
```Python ```Python
""" """
@ -31,7 +31,7 @@ else:
当然如果要构造出更多的分支,可以使用`if…elif…else…`结构,例如下面的分段函数求值。 当然如果要构造出更多的分支,可以使用`if…elif…else…`结构,例如下面的分段函数求值。
$$f(x)=\begin{cases} 3x-5&\text{(x>1)}\\x+2&\text{(-1}\leq\text{x}\leq\text{1)}\\5x+3&\text {(x<-1)}\end{cases}$$ ![$$f(x)=\begin{cases} 3x-5&\text{(x>1)}\\x+2&\text{(-1}\leq\text{x}\leq\text{1)}\\5x+3&\text {(x<-1)}\end{cases}$$](./res/formula_1.png)
```Python ```Python
""" """
@ -79,7 +79,7 @@ else:
print('f(%.2f) = %.2f' % (x, y)) print('f(%.2f) = %.2f' % (x, y))
``` ```
> **说明:**大家可以自己感受一下这两种写法到底是哪一种更好。在之前我们提到的Python之禅中有这么一句话“Flat is better than nested.”,之所以提出这个观点是因为嵌套结构的嵌套层次多了之后会严重的影响代码的可读性,如果可以使用扁平化的结构就不要去用嵌套,因此之前的写法是更好的做法 > **说明:** 大家可以自己感受一下这两种写法到底是哪一种更好。在之前我们提到的Python之禅中有这么一句话“Flat is better than nested.”,之所以提倡代码“扁平化”是因为嵌套结构的嵌套层次多了之后会严重的影响代码的可读性,所以能使用扁平化的结构时就不要使用嵌套
### 练习 ### 练习
@ -130,7 +130,7 @@ else:
result = '讲冷笑话' result = '讲冷笑话'
print(result) print(result)
``` ```
> **说明:**上面的代码中使用了random模块的randint函数生成指定范围的随机数来模拟掷骰子。 > **说明:** 上面的代码中使用了random模块的randint函数生成指定范围的随机数来模拟掷骰子。
#### 练习3百分制成绩转等级制 #### 练习3百分制成绩转等级制
@ -184,7 +184,7 @@ if a + b > c and a + c > b and b + c > a:
else: else:
print('不能构成三角形') print('不能构成三角形')
``` ```
> **说明:**上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。 > **说明:** 上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。
#### 练习5个人所得税计算器。 #### 练习5个人所得税计算器。
@ -227,4 +227,4 @@ tax = abs(diff * rate - deduction)
print('个人所得税: ¥%.2f元' % tax) print('个人所得税: ¥%.2f元' % tax)
print('实际到手收入: ¥%.2f元' % (diff + 3500 - tax)) print('实际到手收入: ¥%.2f元' % (diff + 3500 - tax))
``` ```
>**说明:**上面的代码中使用了Python内置的`abs()`函数取绝对值来处理`-0`的问题。 >**说明:** 上面的代码中使用了Python内置的`abs()`函数取绝对值来处理`-0`的问题。

View File

@ -1,12 +1,14 @@
## Day04 - 循环结构 ## 循环结构
### 循环结构的应用场景 ### 应用场景
如果在程序中我们需要重复的执行某条或某些指令例如用程序控制机器人踢足球如果机器人持球而且还没有进入射门范围那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了刚才的描述中其实不仅仅有需要重复的动作还有我们上一个章节讲到的分支结构。再举一个简单的例子比如在我们的程序中要实现每隔1秒中在屏幕上打印一个&quot;hello, world&quot;这样的字符串并持续一个小时,我们肯定不能够将`print('hello, world')`这句代码写上3600遍如果真的需要这样做那么编程的工作就太无聊了。因此我们需要了解一下循环结构有了循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的发生。在Python中构造循环结构有两种做法一种是`for-in`循环,一种是`while`循环。 如果在程序中我们需要重复的执行某条或某些指令例如用程序控制机器人踢足球如果机器人持球而且还没有进入射门范围那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了刚才的描述中其实不仅仅有需要重复的动作还有我们上一个章节讲到的分支结构。再举一个简单的例子比如在我们的程序中要实现每隔1秒中在屏幕上打印一个&quot;hello, world&quot;这样的字符串并持续一个小时,我们肯定不能够将`print('hello, world')`这句代码写上3600遍如果真的需要这样做那么编程的工作就太无聊了。因此我们还需要了解一下循环结构有了循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的去执行。
在Python中构造循环结构有两种做法一种是`for-in`循环,一种是`while`循环。
### for-in循环 ### for-in循环
如果明确的知道循环执行的次数或者要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算$\sum_{n=1}^{100}n$。 如果明确的知道循环执行的次数或者要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算1~100求和的结果$\displaystyle \sum \limits_{n=1}^{100}n$
```Python ```Python
""" """
@ -63,7 +65,7 @@ print(sum)
### while循环 ### while循环
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`循环继续,表达式的值为`False`循环结束。下面我们通过一个“猜数字”的小游戏计算机出一个1~100之间的随机数人输入自己猜的数字计算机给出对应的提示信息直到人猜出计算机出的数字来看看如何使用`while`循环。 如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`循环继续,表达式的值为`False`循环结束。下面我们通过一个“猜数字”的小游戏计算机出一个1~100之间的随机数人输入自己猜的数字计算机给出对应的提示信息直到人猜出计算机出的数字来看看如何使用`while`循环。
```Python ```Python
""" """
@ -94,7 +96,7 @@ if counter > 7:
print('你的智商余额明显不足') print('你的智商余额明显不足')
``` ```
> **说明:**上面的代码中使用了`break`关键字来提前终止循环,需要注意的是`break`只能终止它所在的那个循环,这一点在使用嵌套的循环结构(下面会讲到)需要引起注意。除了`break`之外,还有另一个关键字是`continue`,它可以用来放弃本次循环后续的代码直接让循环进入下一轮。 > **说明:** 上面的代码中使用了`break`关键字来提前终止循环,需要注意的是`break`只能终止它所在的那个循环,这一点在使用嵌套的循环结构(下面会讲到)需要引起注意。除了`break`之外,还有另一个关键字是`continue`,它可以用来放弃本次循环后续的代码直接让循环进入下一轮。
和分支结构一样,循环结构也是可以嵌套的,也就是说在循环中还可以构造循环结构。下面的例子演示了如何通过嵌套的循环来输出一个九九乘法表。 和分支结构一样,循环结构也是可以嵌套的,也就是说在循环中还可以构造循环结构。下面的例子演示了如何通过嵌套的循环来输出一个九九乘法表。

View File

@ -0,0 +1,13 @@
## 构造程序逻辑
分支和循环结构会帮助我们将程序中逻辑建立起来,将来我们的程序无论简单复杂,都是由顺序结构、分支结构、循环结构构成的。对于编程语言的初学者来说,首先要锻炼的是将人类自然语言描述的解决问题的步骤和方法翻译成代码的能力,其次就是熟练的运用之前学过的运算符、表达式以及最近的两个章节讲解的分支结构和循环结构的知识。有了这些基本的能力才能够通过计算机程序去解决各种各样的现实问题。所以,开始做练习吧!
### 练习清单
1. 寻找[“水仙花数”](https://baike.baidu.com/item/%E6%B0%B4%E4%BB%99%E8%8A%B1%E6%95%B0)。
2. 寻找[“完美数”](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E6%95%B0/370913)。
3. [“百钱百鸡”](https://baike.baidu.com/item/%E7%99%BE%E9%B8%A1%E7%99%BE%E9%92%B1/5857320)问题。
4. 生成[“斐波拉切数列”](https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145)。
5. Craps赌博游戏。
> **提示**练习的参考答案在code/Day05目录下。

View File

@ -2,11 +2,11 @@
在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。 在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。
$$x_1 + x_2 + x_3 + x_4 = 8$$ ![$$x_1 + x_2 + x_3 + x_4 = 8$$](./res/formula_3.png)
事实上上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。 事实上上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。
$$C_M^N =\frac{M!}{N!(M-N)!}, \text{(M=7, N=3)} $$ ![$$C_M^N =\frac{M!}{N!(M-N)!}, \text{(M=7, N=3)} $$](./res/formula_4.png)
可以用Python的程序来计算出这个值代码如下所示。 可以用Python的程序来计算出这个值代码如下所示。
@ -31,7 +31,7 @@ print(fm // fn // fmn)
### 函数的作用 ### 函数的作用
不知道大家是否注意到在上面的代码中我们做了3次求阶乘这样的代码实际上就是重复代码。编程大师Martin Fowler先生曾经说过“代码有很多种坏味道重复是最坏的一种要写出高质量的代码首先要解决的就是重复代码的问题。对于上面的代码来说我们可以将计算阶乘的功能封装到一个称之为“函数”的功能模块中在需要计算阶乘的地方我们只需要“调用”这个“函数”就可以了。 不知道大家是否注意到在上面的代码中我们做了3次求阶乘这样的代码实际上就是重复代码。编程大师*Martin Fowler*先生曾经说过:“**代码有很多种坏味道,重复是最坏的一种!**”,要写出高质量的代码首先要解决的就是重复代码的问题。对于上面的代码来说,我们可以将计算阶乘的功能封装到一个称之为“函数”的功能模块中,在需要计算阶乘的地方,我们只需要“调用”这个“函数”就可以了。
### 定义函数 ### 定义函数
@ -59,7 +59,7 @@ n = int(input('n = '))
print(factorial(m) // factorial(n) // factorial(m - n)) print(factorial(m) // factorial(n) // factorial(m - n))
``` ```
> **说明:**Python的math模块中其实已经有一个factorial函数了事实上要计算阶乘可以直接使用这个现成的函数而不用自己定义。下面例子中的某些函数其实Python中也是内置了我们这里是为了讲解函数的定义和使用才把它们又实现了一遍实际开发中不建议做这种低级的重复性的工作。 > **说明:** Python的math模块中其实已经有一个factorial函数了事实上要计算阶乘可以直接使用这个现成的函数而不用自己定义。下面例子中的某些函数其实Python中也是内置了我们这里是为了讲解函数的定义和使用才把它们又实现了一遍实际开发中不建议做这种低级的重复性的工作。
### 函数的参数 ### 函数的参数
@ -337,7 +337,7 @@ if __name__ == '__main__':
在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对[迪米特法则](https://zh.wikipedia.org/zh-hans/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B)的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在函数调用结束后依然可以访问,这时候就需要使用[闭包](https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)),这个我们在后续的内容中进行讲解。 在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对[迪米特法则](https://zh.wikipedia.org/zh-hans/%E5%BE%97%E5%A2%A8%E5%BF%92%E8%80%B3%E5%AE%9A%E5%BE%8B)的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在函数调用结束后依然可以访问,这时候就需要使用[闭包](https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)),这个我们在后续的内容中进行讲解。
> **说明**很多人经常会将“闭包”一词和[“匿名函数”](https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0)混为一谈,但实际上它们是不同的概念,如果想提前了解这个概念,推荐看看[维基百科](https://zh.wikipedia.org/wiki/)或者[知乎](https://www.zhihu.com/)上对这个概念的讨论。 > **说明** 很多人经常会将“闭包”一词和[“匿名函数”](https://zh.wikipedia.org/wiki/%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0)混为一谈,但实际上它们是不同的概念,如果想提前了解这个概念,推荐看看[维基百科](https://zh.wikipedia.org/wiki/)或者[知乎](https://www.zhihu.com/)上对这个概念的讨论。
说了那么多其实结论很简单从现在开始我们可以将Python代码按照下面的格式进行书写这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。 说了那么多其实结论很简单从现在开始我们可以将Python代码按照下面的格式进行书写这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。

View File

@ -2,7 +2,9 @@
### 使用字符串 ### 使用字符串
第二次世界大战促使了现代电子计算机的诞生当初的想法很简单就是用计算机来计算导弹的弹道因此在计算机刚刚诞生的那个年代计算机处理的信息主要是数值而世界上的第一台电子计算机ENIAC每秒钟能够完成约5000次浮点运算。随着时间的推移虽然对数值运算仍然是计算机日常工作中最为重要的事情之一但是今天的计算机处理得更多的数据都是以文本信息的方式存在的而Python表示文本信息的方式我们在很早以前就说过了那就是字符串类型。所谓**字符串**,就是由零个或多个字符组成的有限序列,一般记为[$${\displaystyle s=a_{1}a_{2}\dots a_{n}(0\leq n \leq \infty)}$$](https://wikimedia.org/api/rest_v1/media/math/render/svg/e29bf631b090323edd6889f810e6cff29538b161)。 第二次世界大战促使了现代电子计算机的诞生最初的目的用计算机来快速的完成导弹弹道的计算因此在计算机刚刚诞生的那个年代计算机处理的信息基本上都是数值型的信息而世界上的第一台电子计算机ENIAC每秒钟能够完成约5000次浮点运算。随着时间的推移虽然数值运算仍然是计算机日常工作中最为重要的事情之一但是今天的计算机更多的时间需要处理的数据可能都是以文本的方式存在的如果我们希望通过Python程序操作本这些文本信息就必须要先了解字符串类型以及与它相关的知识。
所谓**字符串**,就是由零个或多个字符组成的有限序列,一般记为![$${\displaystyle s=a_{1}a_{2}\dots a_{n}(0\leq n \leq \infty)}$$](./res/formula_5.png)。
我们可以通过下面的代码来了解字符串的使用。 我们可以通过下面的代码来了解字符串的使用。
@ -104,8 +106,8 @@ if __name__ == '__main__':
```Python ```Python
def main(): def main():
fruits = ['grape', 'apple', 'strawberry', 'waxberry'] fruits = ['grape', 'apple', 'strawberry', 'waxberry']
fruits += ['pitaya', 'pear', 'mango'] fruits += ['pitaya', 'pear', 'mango']
# 循环遍历列表元素 # 循环遍历列表元素
for fruit in fruits: for fruit in fruits:
print(fruit.title(), end=' ') print(fruit.title(), end=' ')
print() print()
@ -183,11 +185,11 @@ if __name__ == '__main__':
除了上面提到的生成器语法Python中还有另外一种定义生成器的方式就是通过`yield`关键字将一个普通函数改造成生成器函数。下面的代码演示了如何实现一个生成[斐波拉切数列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)的生成器。所谓斐波拉切数列可以通过下面[递归](https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)的方法来进行定义: 除了上面提到的生成器语法Python中还有另外一种定义生成器的方式就是通过`yield`关键字将一个普通函数改造成生成器函数。下面的代码演示了如何实现一个生成[斐波拉切数列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)的生成器。所谓斐波拉切数列可以通过下面[递归](https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)的方法来进行定义:
$${\displaystyle F_{0}=0}$$ ![$${\displaystyle F_{0}=0}$$](./res/formula_6.png)
$${\displaystyle F_{1}=1}$$ ![$${\displaystyle F_{1}=1}$$](./res/formula_7.png)
$${\displaystyle F_{n}=F_{n-1}+F_{n-2}}({n}\geq{2})$$ ![$${\displaystyle F_{n}=F_{n-1}+F_{n-2}}({n}\geq{2})$$](./res/formula_8.png)
![](./res/fibonacci-blocks.png) ![](./res/fibonacci-blocks.png)
@ -307,7 +309,7 @@ if __name__ == '__main__':
main() main()
``` ```
> **说明**Python中允许通过一些特殊的方法来为某种类型或数据结构自定义运算符后面的章节中会讲到上面的代码中我们对集合进行运算的时候可以调用集合对象的方法也可以直接使用对应的运算符例如`&`运算符跟intersection方法的作用就是一样的但是使用运算符让代码更加直观。 > **说明** Python中允许通过一些特殊的方法来为某种类型或数据结构自定义运算符后面的章节中会讲到上面的代码中我们对集合进行运算的时候可以调用集合对象的方法也可以直接使用对应的运算符例如`&`运算符跟intersection方法的作用就是一样的但是使用运算符让代码更加直观。
### 使用字典 ### 使用字典
@ -530,7 +532,7 @@ if __name__ == '__main__':
main() main()
``` ```
> **说明**上面使用random模块的sample函数来实现从列表中选择不重复的n个元素。 > **说明** 上面使用random模块的sample函数来实现从列表中选择不重复的n个元素。
#### 综合案例2[约瑟夫环问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98) #### 综合案例2[约瑟夫环问题](https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98)
@ -609,4 +611,4 @@ if __name__ == '__main__':
main() main()
``` ```
>**说明**最后这个案例来自[《Python编程快速上手:让繁琐工作自动化》](https://item.jd.com/11943853.html)一书这本书对有编程基础想迅速使用Python将日常工作自动化的人来说还是不错的选择对代码做了一点点的调整。 >**说明** 最后这个案例来自[《Python编程快速上手:让繁琐工作自动化》](https://item.jd.com/11943853.html)一书这本书对有编程基础想迅速使用Python将日常工作自动化的人来说还是不错的选择对代码做了一点点的调整。

View File

@ -2,19 +2,19 @@
活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。 活在当下的程序员应该都听过“面向对象编程”一词,也经常有人问能不能用一句话解释下什么是“面向对象编程”,我们先来看看比较正式的说法。
> 把一组数据结构和处理它们的方法组成对象object把相同行为的对象归纳为类class通过类的封装encapsulation隐藏内部细节通过继承inheritance实现类的特化specialization和泛化generalization通过多态polymorphism实现基于对象类型的动态分派。 把一组数据结构和处理它们的方法组成对象object把相同行为的对象归纳为类class通过类的封装encapsulation隐藏内部细节通过继承inheritance实现类的特化specialization和泛化generalization通过多态polymorphism实现基于对象类型的动态分派。
这样一说是不是更不明白了。所以我们还是看看更通俗易懂的说法,下面这段内容来自于[知乎](https://www.zhihu.com/)。 这样一说是不是更不明白了。所以我们还是看看更通俗易懂的说法,下面这段内容来自于[知乎](https://www.zhihu.com/)。
![](./res/oop-zhihu.png) ![](./res/oop-zhihu.png)
> **说明**以上的内容来自于网络,不代表作者本人的观点和看法,与作者本人立场无关,相关责任不由作者承担。 > **说明** 以上的内容来自于网络,不代表作者本人的观点和看法,与作者本人立场无关,相关责任不由作者承担。
之前我们说过“程序是指令的集合”我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计我们引入了函数的概念把相对独立且经常重复使用的代码放置到函数中在需要使用这些功能的时候只要调用函数即可如果一个函数的功能过于复杂和臃肿我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多不知道大家是否发现所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是计算机的工作方式与正常人类的思维模式是不同的如果编程就必须得抛弃人类正常的思维方式去迎合计算机编程的乐趣就少了很多“每个人都应该学习编程”这样的豪言壮语就只能说说而已。当然这些还不是最重要的最重要的是当我们需要开发一个复杂的系统时代码的复杂性会让开发和维护工作都变得举步维艰所以在上世纪60年代末期“[软件危机](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%8D%B1%E6%9C%BA)”、“[软件工程](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B)”等一系列的概念开始在行业中出现。 之前我们说过“程序是指令的集合”我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计我们引入了函数的概念把相对独立且经常重复使用的代码放置到函数中在需要使用这些功能的时候只要调用函数即可如果一个函数的功能过于复杂和臃肿我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多不知道大家是否发现所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是计算机的工作方式与正常人类的思维模式是不同的如果编程就必须得抛弃人类正常的思维方式去迎合计算机编程的乐趣就少了很多“每个人都应该学习编程”这样的豪言壮语就只能说说而已。当然这些还不是最重要的最重要的是当我们需要开发一个复杂的系统时代码的复杂性会让开发和维护工作都变得举步维艰所以在上世纪60年代末期“[软件危机](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%8D%B1%E6%9C%BA)”、“[软件工程](https://zh.wikipedia.org/wiki/%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B)”等一系列的概念开始在行业中出现。
当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的“[银弹](https://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9)”真正让软件开发者看到希望的是上世纪70年代诞生的[Smalltalk](https://zh.wikipedia.org/wiki/Smalltalk)编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的[Simula](https://zh.wikipedia.org/wiki/Simula)语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。 当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的“[银弹](https://zh.wikipedia.org/wiki/%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9)”真正让软件开发者看到希望的是上世纪70年代诞生的[Smalltalk](https://zh.wikipedia.org/wiki/Smalltalk)编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的[Simula](https://zh.wikipedia.org/wiki/Simula)语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。
> **说明**当然面向对象也不是解决软件开发中所有问题的最后的“银弹”所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持Python也不例外。 > **说明** 当然面向对象也不是解决软件开发中所有问题的最后的“银弹”所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持Python也不例外。
### 类和对象 ### 类和对象
@ -39,15 +39,15 @@ class Student(object):
print('%s正在学习%s.' % (self.name, course_name)) print('%s正在学习%s.' % (self.name, course_name))
# PEP 8要求标识符的名字用全小写多个单词用下划线连接 # PEP 8要求标识符的名字用全小写多个单词用下划线连接
# 但是很多程序员和公司更倾向于使用驼峰命名法(驼峰标识) # 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)
def watch_av(self): def watch_movie(self):
if self.age < 18: if self.age < 18:
print('%s只能观看《熊出没》.' % self.name) print('%s只能观看《熊出没》.' % self.name)
else: else:
print('%s正在观看岛国爱情动作片.' % self.name print('%s正在观看岛国爱情大电影.' % self.name)
``` ```
> **说明**写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。 > **说明** 写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。
### 创建和使用对象 ### 创建和使用对象
@ -60,10 +60,10 @@ def main():
# 给对象发study消息 # 给对象发study消息
stu1.study('Python程序设计') stu1.study('Python程序设计')
# 给对象发watch_av消息 # 给对象发watch_av消息
stu1.watch_av() stu1.watch_movie()
stu2 = Student('王大锤', 15) stu2 = Student('王大锤', 15)
stu2.study('思想品德') stu2.study('思想品德')
stu2.watch_av() stu2.watch_movie()
if __name__ == '__main__': if __name__ == '__main__':
@ -131,6 +131,9 @@ if __name__ == "__main__":
#### 练习1定义一个类描述数字时钟 #### 练习1定义一个类描述数字时钟
```Python ```Python
from time import sleep
class Clock(object): class Clock(object):
"""数字时钟""" """数字时钟"""
@ -237,4 +240,4 @@ if __name__ == '__main__':
main() main()
``` ```
> **说明**本章中的插图来自于Grady Booch等著作的[《面向对象分析与设计》](https://item.jd.com/20476561918.html)一书,该书是讲解面向对象编程的经典著作,有兴趣的读者可以购买和阅读这本书来了解更多的面向对象的相关知识。 > **说明** 本章中的插图来自于Grady Booch等著作的[《面向对象分析与设计》](https://item.jd.com/20476561918.html)一书,该书是讲解面向对象编程的经典著作,有兴趣的读者可以购买和阅读这本书来了解更多的面向对象的相关知识。

View File

@ -276,7 +276,7 @@ def main():
stu = Student('王大锤', 15, '初三') stu = Student('王大锤', 15, '初三')
stu.study('数学') stu.study('数学')
stu.watch_av() stu.watch_av()
t = Teacher('骆昊', 38, '老叫兽') t = Teacher('骆昊', 38, '砖家')
t.teach('Python程序设计') t.teach('Python程序设计')
t.watch_av() t.watch_av()
@ -636,7 +636,7 @@ if __name__ == '__main__':
main() main()
``` ```
>**说明**大家可以自己尝试在上面代码的基础上写一个简单的扑克游戏例如21点(Black Jack),游戏的规则可以自己在网上找一找。 >**说明** 大家可以自己尝试在上面代码的基础上写一个简单的扑克游戏例如21点(Black Jack),游戏的规则可以自己在网上找一找。
#### 案例3工资结算系统 #### 案例3工资结算系统

View File

@ -128,7 +128,7 @@ if __name__ == '__main__':
main() main()
``` ```
####加载图像 #### 加载图像
如果需要直接加载图像到窗口上可以使用pygame中image模块的函数来加载图像再通过之前获得的窗口对象的`blit`方法渲染图像,代码如下所示。 如果需要直接加载图像到窗口上可以使用pygame中image模块的函数来加载图像再通过之前获得的窗口对象的`blit`方法渲染图像,代码如下所示。
@ -164,7 +164,7 @@ if __name__ == '__main__':
main() main()
``` ```
####实现动画效果 #### 实现动画效果
说到[动画](https://zh.wikipedia.org/wiki/%E5%8A%A8%E7%94%BB)这个词大家都不会陌生,事实上要实现动画效果,本身的原理也非常简单,就是将不连续的图片连续的播放,只要每秒钟达到了一定的帧数,那么就可以做出比较流畅的动画效果。如果要让上面代码中的小球动起来,可以将小球的位置用变量来表示,并在循环中修改小球的位置再刷新整个窗口即可。 说到[动画](https://zh.wikipedia.org/wiki/%E5%8A%A8%E7%94%BB)这个词大家都不会陌生,事实上要实现动画效果,本身的原理也非常简单,就是将不连续的图片连续的播放,只要每秒钟达到了一定的帧数,那么就可以做出比较流畅的动画效果。如果要让上面代码中的小球动起来,可以将小球的位置用变量来表示,并在循环中修改小球的位置再刷新整个窗口即可。

View File

@ -1,6 +1,6 @@
## 文件和异常 ## 文件和异常
在实际开发中,常常需要对程序中的数据进行[持久化](https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96)操作,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于[文件系统](https://zh.wikipedia.org/wiki/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F)的知识,对于这个概念,维基百科上给出了很好的诠释,这里不再浪费笔墨 实际开发中常常会遇到对数据进行[持久化](https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96)操作的场景,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于[文件系统](https://zh.wikipedia.org/wiki/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F)的知识,但是这里我们并不浪费笔墨介绍这个概念,请大家自行通过维基百科进行了解
在Python中实现文件的读写操作其实非常简单通过Python内置的`open`函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。这里所说的操作模式是指要打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加),具体的如下表所示。 在Python中实现文件的读写操作其实非常简单通过Python内置的`open`函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。这里所说的操作模式是指要打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加),具体的如下表所示。
@ -103,7 +103,7 @@ if __name__ == '__main__':
main() main()
``` ```
要将文本信息写入文件文件也非常简单,在使用`open`函数时指定好文件名并将文件模式设置为`'w'`即可。注意如果需要对文件内容进行追加式写入,应该将模式设置为`'a'`。如果要写入的文件不存在会自动创建文件而不是引发异常。下面的例子演示了如何将1-9999直接的素数分别写入三个文件中1-99之间的素数保存在a.txt中100-999之间的素数保存在b.txt中1000-9999之间的素数保存在c.txt中 要将文本信息写入文件文件也非常简单,在使用`open`函数时指定好文件名并将文件模式设置为`'w'`即可。注意如果需要对文件内容进行追加式写入,应该将模式设置为`'a'`。如果要写入的文件不存在会自动创建文件而不是引发异常。下面的例子演示了如何将1-9999之间的素数分别写入三个文件中1-99之间的素数保存在a.txt中100-999之间的素数保存在b.txt中1000-9999之间的素数保存在c.txt中
```Python ```Python
from math import sqrt from math import sqrt
@ -174,14 +174,14 @@ if __name__ == '__main__':
```JSON ```JSON
{ {
'name': '骆昊', "name": "骆昊",
'age': 38, "age": 38,
'qq': 957658, "qq": 957658,
'friends': ['王大锤', '白元芳'], "friends": ["王大锤", "白元芳"],
'cars': [ "cars": [
{'brand': 'BYD', 'max_speed': 180}, {"brand": "BYD", "max_speed": 180},
{'brand': 'Audi', 'max_speed': 280}, {"brand": "Audi", "max_speed": 280},
{'brand': 'Benz', 'max_speed': 320} {"brand": "Benz", "max_speed": 320}
] ]
} }
``` ```

View File

@ -32,7 +32,7 @@
| \| | 分支 | foo\|bar | 可以匹配foo或者bar | | \| | 分支 | foo\|bar | 可以匹配foo或者bar |
| (?#) | 注释 | | | | (?#) | 注释 | | |
| (exp) | 匹配exp并捕获到自动命名的组中 | | | | (exp) | 匹配exp并捕获到自动命名的组中 | | |
| (?&lt;name&gt;exp) | 匹配exp并捕获到名为name的组中 | | | | (?&nbsp;&lt;name&gt;exp) | 匹配exp并捕获到名为name的组中 | | |
| (?:exp) | 匹配exp但是不捕获匹配的文本 | | | | (?:exp) | 匹配exp但是不捕获匹配的文本 | | |
| (?=exp) | 匹配exp前面的位置 | \\b\\w+(?=ing) | 可以匹配I'm dancing中的danc | | (?=exp) | 匹配exp前面的位置 | \\b\\w+(?=ing) | 可以匹配I'm dancing中的danc |
| (?<=exp) | 匹配exp后面的位置 | (?<=\\bdanc)\\w+\\b | 可以匹配I love dancing and reading中的第一个ing | | (?<=exp) | 匹配exp后面的位置 | (?<=\\bdanc)\\w+\\b | 可以匹配I love dancing and reading中的第一个ing |
@ -44,7 +44,7 @@
| {M,N}? | 重复M到N次但尽可能少重复 | | | | {M,N}? | 重复M到N次但尽可能少重复 | | |
| {M,}? | 重复M次以上但尽可能少重复 | | | | {M,}? | 重复M次以上但尽可能少重复 | | |
> **说明:**如果需要匹配的字符是正则表达式中的特殊字符,那么可以使用\\进行转义处理,例如想匹配小数点可以写成\\.就可以了,因为直接写.会匹配任意字符;同理,想匹配圆括号必须写成\\(和\\),否则圆括号被视为正则表达式中的分组。 > **说明:** 如果需要匹配的字符是正则表达式中的特殊字符,那么可以使用\\进行转义处理,例如想匹配小数点可以写成\\.就可以了,因为直接写.会匹配任意字符;同理,想匹配圆括号必须写成\\(和\\),否则圆括号被视为正则表达式中的分组。
### Python对正则表达式的支持 ### Python对正则表达式的支持
@ -64,7 +64,7 @@ Python提供了re模块来支持正则表达式相关操作下面是re模块
| re.I / re.IGNORECASE | 忽略大小写匹配标记 | | re.I / re.IGNORECASE | 忽略大小写匹配标记 |
| re.M / re.MULTILINE | 多行匹配标记 | | re.M / re.MULTILINE | 多行匹配标记 |
> **说明:**上面提到的re模块中的这些函数实际开发中也可以用正则表达式对象的方法替代对这些函数的使用如果一个正则表达式需要重复的使用那么先通过compile函数编译正则表达式并创建出正则表达式对象无疑是更为明智的选择。 > **说明:** 上面提到的re模块中的这些函数实际开发中也可以用正则表达式对象的方法替代对这些函数的使用如果一个正则表达式需要重复的使用那么先通过compile函数编译正则表达式并创建出正则表达式对象无疑是更为明智的选择。
下面我们通过一系列的例子来告诉大家在Python中如何使用正则表达式。 下面我们通过一系列的例子来告诉大家在Python中如何使用正则表达式。
@ -98,7 +98,7 @@ if __name__ == '__main__':
main() main()
``` ```
> **提示**上面在书写正则表达式时使用了“原始字符串”的写法在字符串前面加上了r所谓“原始字符串”就是字符串中的每个字符都是它原始的意义说得更直接一点就是字符串中没有所谓的转义字符啦。因为正则表达式中有很多元字符和需要进行转义的地方如果不使用原始字符串就需要将反斜杠写作\\\\,例如表示数字的\\d得书写成\\\\d这样不仅写起来不方便阅读的时候也会很吃力。 > **提示** 上面在书写正则表达式时使用了“原始字符串”的写法在字符串前面加上了r所谓“原始字符串”就是字符串中的每个字符都是它原始的意义说得更直接一点就是字符串中没有所谓的转义字符啦。因为正则表达式中有很多元字符和需要进行转义的地方如果不使用原始字符串就需要将反斜杠写作\\\\,例如表示数字的\\d得书写成\\\\d这样不仅写起来不方便阅读的时候也会很吃力。
#### 例子2从一段文字中提取出国内手机号码。 #### 例子2从一段文字中提取出国内手机号码。
@ -136,7 +136,7 @@ if __name__ == '__main__':
main() main()
``` ```
> **说明**上面匹配国内手机号的正则表达式并不够好因为像14开头的号码只有145或147而上面的正则表达式并没有考虑这种情况要匹配国内手机号更好的正则表达式的写法是`(?<=\D)(1[38]\d{9}|14[57]\d{8}|15[0-35-9]\d{8}|17[678]\d{8})(?=\D)`国内最近好像有19和16开头的手机号了但是这个暂时不在我们考虑之列。 > **说明** 上面匹配国内手机号的正则表达式并不够好因为像14开头的号码只有145或147而上面的正则表达式并没有考虑这种情况要匹配国内手机号更好的正则表达式的写法是`(?<=\D)(1[38]\d{9}|14[57]\d{8}|15[0-35-9]\d{8}|17[678]\d{8})(?=\D)`国内最近好像有19和16开头的手机号了但是这个暂时不在我们考虑之列。
#### 例子3替换字符串中的不良内容 #### 例子3替换字符串中的不良内容
@ -155,7 +155,7 @@ if __name__ == '__main__':
main() main()
``` ```
> **说明**re模块的正则表达式相关函数中都有一个flags参数它代表了正则表达式的匹配标记可以通过该标记来指定匹配时是否忽略大小写、是否进行多行匹配、是否显示调试信息等。如果需要为flags参数指定多个值可以使用[按位或运算符](http://www.runoob.com/python/python-operators.html#ysf5)进行叠加,如`flags=re.I | re.M`。 > **说明** re模块的正则表达式相关函数中都有一个flags参数它代表了正则表达式的匹配标记可以通过该标记来指定匹配时是否忽略大小写、是否进行多行匹配、是否显示调试信息等。如果需要为flags参数指定多个值可以使用[按位或运算符](http://www.runoob.com/python/python-operators.html#ysf5)进行叠加,如`flags=re.I | re.M`。
#### 例子4拆分长字符串 #### 例子4拆分长字符串

View File

@ -320,7 +320,7 @@ if __name__ == '__main__':
除了计算密集型任务其他的涉及到网络、存储介质I/O的任务都可以视为I/O密集型任务这类任务的特点是CPU消耗很少任务的大部分时间都在等待I/O操作完成因为I/O的速度远远低于CPU和内存的速度。对于I/O密集型任务如果启动多任务就可以减少I/O等待时间从而让CPU高效率的运转。有一大类的任务都属于I/O密集型任务这其中包括了我们很快会涉及到的网络应用和Web应用。 除了计算密集型任务其他的涉及到网络、存储介质I/O的任务都可以视为I/O密集型任务这类任务的特点是CPU消耗很少任务的大部分时间都在等待I/O操作完成因为I/O的速度远远低于CPU和内存的速度。对于I/O密集型任务如果启动多任务就可以减少I/O等待时间从而让CPU高效率的运转。有一大类的任务都属于I/O密集型任务这其中包括了我们很快会涉及到的网络应用和Web应用。
> **说明:**上面的内容和例子来自于[廖雪峰官方网站的《Python教程》](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000),因为对作者文中的某些观点持有不同的看法,对原文的文字描述做了适当的调整。 > **说明:** 上面的内容和例子来自于[廖雪峰官方网站的《Python教程》](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000),因为对作者文中的某些观点持有不同的看法,对原文的文字描述做了适当的调整。
### 单线程+异步I/O ### 单线程+异步I/O
@ -485,5 +485,5 @@ if __name__ == '__main__':
main() main()
``` ```
比较两段代码的执行结果在我目前使用的MacBook上上面的代码需要大概6秒左右的时间而下面的代码只需要不到1秒的时间再强调一次我们只是比较了运算的时间不考虑列表创建及切片操作花费的时间使用多进程后由于获得了更多的CPU执行时间以及更好的利用了CPU的多核特性明显的减少了程序的执行时间而且计算量越大效果越明显。当然如果愿意还可以将多个进程部署在不同的计算机上做成分布式进程具体的做法就是通过multiprocessing.managers模块中提供的管理器将`Queue`对象通过网络共享出来(注册到网络上让其他计算机可以访问),这部分内容也留到爬虫的专题再进行讲解。 比较两段代码的执行结果在我目前使用的MacBook上上面的代码需要大概6秒左右的时间而下面的代码只需要不到1秒的时间再强调一次我们只是比较了运算的时间不考虑列表创建及切片操作花费的时间使用多进程后由于获得了更多的CPU执行时间以及更好的利用了CPU的多核特性明显的减少了程序的执行时间而且计算量越大效果越明显。当然如果愿意还可以将多个进程部署在不同的计算机上做成分布式进程具体的做法就是通过`multiprocessing.managers`模块中提供的管理器将`Queue`对象通过网络共享出来(注册到网络上让其他计算机可以访问),这部分内容也留到爬虫的专题再进行讲解。

View File

@ -38,8 +38,6 @@ TCP全称传输控制协议它是基于IP提供的寻址和路由服务而建
2. 流量控制(通过滑动窗口匹配数据发送者和接收者之间的传输速度)。 2. 流量控制(通过滑动窗口匹配数据发送者和接收者之间的传输速度)。
3. 拥塞控制通过RTT时间以及对滑动窗口的控制缓解网络拥堵 3. 拥塞控制通过RTT时间以及对滑动窗口的控制缓解网络拥堵
#### 网络应用模式 #### 网络应用模式
1. C/S模式和B/S模式。这里的C指的是Client客户端通常是一个需要安装到某个宿主操作系统上的应用程序而B指的是Browser浏览器它几乎是所有图形化操作系统都默认安装了的一个应用软件通过C或B都可以实现对S服务器的访问。关于二者的比较和讨论在网络上有一大堆的文章在此我们就不再浪费笔墨了。 1. C/S模式和B/S模式。这里的C指的是Client客户端通常是一个需要安装到某个宿主操作系统上的应用程序而B指的是Browser浏览器它几乎是所有图形化操作系统都默认安装了的一个应用软件通过C或B都可以实现对S服务器的访问。关于二者的比较和讨论在网络上有一大堆的文章在此我们就不再浪费笔墨了。
@ -70,9 +68,9 @@ JSON的例子
```JSON ```JSON
{ {
'from': 'Alice', "from": "Alice",
'to': 'Bob', "to": "Bob",
'content': 'Will you marry me?' "content": "Will you marry me?"
} }
``` ```
@ -291,9 +289,129 @@ if __name__ == '__main__':
在这个案例中我们使用了JSON作为数据传输的格式通过JSON格式对传输的数据进行了序列化和反序列化的操作但是JSON并不能携带二进制数据因此对图片的二进制数据进行了Base64编码的处理。Base64是一种用64个字符表示所有二进制数据的编码方式通过将二进制数据每6位一组的方式重新组织刚好可以使用0~9的数字、大小写字母以及“+”和“/”总共64个字符表示从`000000`到`111111`的64种状态。[维基百科](https://zh.wikipedia.org/wiki/Base64)上有关于Base64编码的详细讲解不熟悉Base64的读者可以自行阅读。 在这个案例中我们使用了JSON作为数据传输的格式通过JSON格式对传输的数据进行了序列化和反序列化的操作但是JSON并不能携带二进制数据因此对图片的二进制数据进行了Base64编码的处理。Base64是一种用64个字符表示所有二进制数据的编码方式通过将二进制数据每6位一组的方式重新组织刚好可以使用0~9的数字、大小写字母以及“+”和“/”总共64个字符表示从`000000`到`111111`的64种状态。[维基百科](https://zh.wikipedia.org/wiki/Base64)上有关于Base64编码的详细讲解不熟悉Base64的读者可以自行阅读。
> **说明**上面的代码主要为了讲解网络编程的相关内容因此并没有对异常状况进行处理,请读者自行添加异常处理代码来增强程序的健壮性。 > **说明** 上面的代码主要为了讲解网络编程的相关内容因此并没有对异常状况进行处理,请读者自行添加异常处理代码来增强程序的健壮性。
#### UDP套接字 #### UDP套接字
传输层除了有可靠的传输协议TCP之外还有一种非常轻便的传输协议叫做用户数据报协议简称UDP。TCP和UDP都是提供端到端传输服务的协议二者的差别就如同打电话和发短信的区别后者不对传输的可靠性和可达性做出任何承诺从而避免了TCP中握手和重传的开销所以在强调性能和而不是数据完整性的场景中例如传输网络音视频数据UDP可能是更好的选择。可能大家会注意到一个现象就是在观看网络视频时有时会出现卡顿有时会出现花屏这无非就是部分数据传丢或传错造成的。在Python中也可以使用UDP套接字来创建网络应用对此我们不进行赘述有兴趣的读者可以自行研究。 传输层除了有可靠的传输协议TCP之外还有一种非常轻便的传输协议叫做用户数据报协议简称UDP。TCP和UDP都是提供端到端传输服务的协议二者的差别就如同打电话和发短信的区别后者不对传输的可靠性和可达性做出任何承诺从而避免了TCP中握手和重传的开销所以在强调性能和而不是数据完整性的场景中例如传输网络音视频数据UDP可能是更好的选择。可能大家会注意到一个现象就是在观看网络视频时有时会出现卡顿有时会出现花屏这无非就是部分数据传丢或传错造成的。在Python中也可以使用UDP套接字来创建网络应用对此我们不进行赘述有兴趣的读者可以自行研究。
### 网络应用开发
#### 发送电子邮件
在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知、网站向用户发送一个激活账号的链接、银行向客户推广它们的理财产品等几乎都是通过电子邮件来完成的,而这些任务应该都是由程序自动完成的。
就像我们可以用HTTP超文本传输协议来访问一个网站一样发送邮件要使用SMTP简单邮件传输协议SMTP也是一个建立在TCP传输控制协议提供的可靠数据传输服务的基础上的应用级协议它规定了邮件的发送者如何跟发送邮件的服务器进行通信的细节而Python中的smtplib模块将这些操作简化成了几个简单的函数。
下面的代码演示了如何在Python发送邮件。
```Python
from smtplib import SMTP
from email.header import Header
from email.mime.text import MIMEText
def main():
# 请自行修改下面的邮件发送者和接收者
sender = 'abcdefg@126.com'
receivers = ['uvwxyz@qq.com', 'uvwxyz@126.com']
message = MIMEText('用Python发送邮件的示例代码.', 'plain', 'utf-8')
message['From'] = Header('王大锤', 'utf-8')
message['To'] = Header('骆昊', 'utf-8')
message['Subject'] = Header('示例代码实验邮件', 'utf-8')
smtper = SMTP('smtp.126.com')
# 请自行修改下面的登录口令
smtper.login(sender, 'secretpass')
smtper.sendmail(sender, receivers, message.as_string())
print('邮件发送完成!')
if __name__ == '__main__':
main()
```
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
```Python
from smtplib import SMTP
from email.header import Header
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import urllib
def main():
# 创建一个带附件的邮件消息对象
message = MIMEMultipart()
# 创建文本内容
text_content = MIMEText('附件中有本月数据请查收', 'plain', 'utf-8')
message['Subject'] = Header('本月数据', 'utf-8')
# 将文本内容添加到邮件消息对象中
message.attach(text_content)
# 读取文件并将文件作为附件添加到邮件消息对象中
with open('/Users/Hao/Desktop/hello.txt', 'rb') as f:
txt = MIMEText(f.read(), 'base64', 'utf-8')
txt['Content-Type'] = 'text/plain'
txt['Content-Disposition'] = 'attachment; filename=hello.txt'
message.attach(txt)
# 读取文件并将文件作为附件添加到邮件消息对象中
with open('/Users/Hao/Desktop/汇总数据.xlsx', 'rb') as f:
xls = MIMEText(f.read(), 'base64', 'utf-8')
xls['Content-Type'] = 'application/vnd.ms-excel'
xls['Content-Disposition'] = 'attachment; filename=month-data.xlsx'
message.attach(xls)
# 创建SMTP对象
smtper = SMTP('smtp.126.com')
# 开启安全连接
# smtper.starttls()
sender = 'abcdefg@126.com'
receivers = ['uvwxyz@qq.com']
# 登录到SMTP服务器
# 请注意此处不是使用密码而是邮件客户端授权码进行登录
# 对此有疑问的读者可以联系自己使用的邮件服务器客服
smtper.login(sender, 'secretpass')
# 发送邮件
smtper.sendmail(sender, receivers, message.as_string())
# 与邮件服务器断开连接
smtper.quit()
print('发送完成!')
if __name__ == '__main__':
main()
```
#### 发送短信
发送短信也是项目中常见的功能,网站的注册码、验证码、营销信息基本上都是通过短信来发送给用户的。在下面的代码中我们使用了[互亿无线](http://www.ihuyi.com/)短信平台该平台为注册用户提供了50条免费短信以及常用开发语言发送短信的demo可以登录该网站并在用户自服务页面中对短信进行配置提供的API接口实现了发送短信的服务当然国内的短信平台很多读者可以根据自己的需要进行选择通常会考虑费用预算、短信达到率、使用的难易程度等指标如果需要在商业项目中使用短信服务建议购买短信平台提供的套餐服务。
```Python
import urllib.parse
import http.client
import json
def main():
host = "106.ihuyi.com"
sms_send_uri = "/webservice/sms.php?method=Submit"
# 下面的参数需要填入自己注册的账号和对应的密码
params = urllib.parse.urlencode({'account': '你自己的账号', 'password' : '你自己的密码', 'content': '您的验证码是147258。请不要把验证码泄露给其他人。', 'mobile': '接收者的手机号', 'format':'json' })
print(params)
headers = {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}
conn = http.client.HTTPConnection(host, port=80, timeout=30)
conn.request('POST', sms_send_uri, params, headers)
response = conn.getresponse()
response_str = response.read()
jsonstr = response_str.decode('utf-8')
print(json.loads(jsonstr))
conn.close()
if __name__ == '__main__':
main()
```

View File

@ -76,7 +76,7 @@ Pillow中最为重要的是Image类读取和处理图像都要通过这个类
```Python ```Python
>>> image = Image.open('./res/guido.png') >>> image = Image.open('./res/guido.png')
>>> image.rotata(180).show() >>> image.rotate(180).show()
>>> image.transpose(Image.FLIP_LEFT_RIGHT).show() >>> image.transpose(Image.FLIP_LEFT_RIGHT).show()
``` ```

View File

@ -1,9 +0,0 @@
## 练习
### 练习清单
1. 寻找[“水仙花数”](https://baike.baidu.com/item/%E6%B0%B4%E4%BB%99%E8%8A%B1%E6%95%B0)。
2. 寻找[“完美数”](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E6%95%B0/370913)。
3. [“百钱百鸡”](https://baike.baidu.com/item/%E7%99%BE%E9%B8%A1%E7%99%BE%E9%92%B1/5857320)问题。
4. 生成[“斐波拉切数列”](https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145)。
5. Craps赌博游戏。

File diff suppressed because one or more lines are too long

View File

@ -1,121 +0,0 @@
## 网络应用开发
### 发送电子邮件
在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知、网站向用户发送一个激活账号的链接、银行向客户推广它们的理财产品等几乎都是通过电子邮件来完成的,而这些任务应该都是由程序自动完成的。
就像我们可以用HTTP超文本传输协议来访问一个网站一样发送邮件要使用SMTP简单邮件传输协议SMTP也是一个建立在TCP传输控制协议提供的可靠数据传输服务的基础上的应用级协议它规定了邮件的发送者如何跟发送邮件的服务器进行通信的细节而Python中的smtplib模块将这些操作简化成了几个简单的函数。
下面的代码演示了如何在Python发送邮件。
```Python
from smtplib import SMTP
from email.header import Header
from email.mime.text import MIMEText
def main():
# 请自行修改下面的邮件发送者和接收者
sender = 'abcdefg@126.com'
receivers = ['uvwxyz@qq.com', 'uvwxyz@126.com']
message = MIMEText('用Python发送邮件的示例代码.', 'plain', 'utf-8')
message['From'] = Header('王大锤', 'utf-8')
message['To'] = Header('骆昊', 'utf-8')
message['Subject'] = Header('示例代码实验邮件', 'utf-8')
smtper = SMTP('smtp.126.com')
# 请自行修改下面的登录口令
smtper.login(sender, 'secretpass')
smtper.sendmail(sender, receivers, message.as_string())
print('邮件发送完成!')
if __name__ == '__main__':
main()
```
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
```Python
from smtplib import SMTP
from email.header import Header
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import urllib
def main():
# 创建一个带附件的邮件消息对象
message = MIMEMultipart()
# 创建文本内容
text_content = MIMEText('附件中有本月数据请查收', 'plain', 'utf-8')
message['Subject'] = Header('本月数据', 'utf-8')
# 将文本内容添加到邮件消息对象中
message.attach(text_content)
# 读取文件并将文件作为附件添加到邮件消息对象中
with open('/Users/Hao/Desktop/hello.txt', 'rb') as f:
txt = MIMEText(f.read(), 'base64', 'utf-8')
txt['Content-Type'] = 'text/plain'
txt['Content-Disposition'] = 'attachment; filename=hello.txt'
message.attach(txt)
# 读取文件并将文件作为附件添加到邮件消息对象中
with open('/Users/Hao/Desktop/汇总数据.xlsx', 'rb') as f:
xls = MIMEText(f.read(), 'base64', 'utf-8')
xls['Content-Type'] = 'application/vnd.ms-excel'
xls['Content-Disposition'] = 'attachment; filename=month-data.xlsx'
message.attach(xls)
# 创建SMTP对象
smtper = SMTP('smtp.126.com')
# 开启安全连接
# smtper.starttls()
sender = 'abcdefg@126.com'
receivers = ['uvwxyz@qq.com']
# 登录到SMTP服务器
# 请注意此处不是使用密码而是邮件客户端授权码进行登录
# 对此有疑问的读者可以联系自己使用的邮件服务器客服
smtper.login(sender, 'secretpass')
# 发送邮件
smtper.sendmail(sender, receivers, message.as_string())
# 与邮件服务器断开连接
smtper.quit()
print('发送完成!')
if __name__ == '__main__':
main()
```
### 发送短信
发送短信也是项目中常见的功能,网站的注册码、验证码、营销信息基本上都是通过短信来发送给用户的。在下面的代码中我们使用了[互亿无线](http://www.ihuyi.com/)短信平台该平台为注册用户提供了50条免费短信以及常用开发语言发送短信的demo可以登录该网站并在用户自服务页面中对短信进行配置提供的API接口实现了发送短信的服务当然国内的短信平台很多读者可以根据自己的需要进行选择通常会考虑费用预算、短信达到率、使用的难易程度等指标如果需要在商业项目中使用短信服务建议购买短信平台提供的套餐服务。
```Python
import urllib.parse
import http.client
import json
def main():
host = "106.ihuyi.com"
sms_send_uri = "/webservice/sms.php?method=Submit"
# 下面的参数需要填入自己注册的账号和对应的密码
params = urllib.parse.urlencode({'account': '你自己的账号', 'password' : '你自己的密码', 'content': '您的验证码是147258。请不要把验证码泄露给其他人。', 'mobile': '接收者的手机号', 'format':'json' })
print(params)
headers = {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}
conn = http.client.HTTPConnection(host, port=80, timeout=30)
conn.request('POST', sms_send_uri, params, headers)
response = conn.getresponse()
response_str = response.read()
jsonstr = response_str.decode('utf-8')
print(json.loads(jsonstr))
conn.close()
if __name__ == '__main__':
main()
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

View File

@ -6,8 +6,13 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-26 Date: 2018-02-26
请将该文件命名为hello.py并在终端中通过下面的命令运行它 请将该文件命名为hello.py
使用Windows的小伙伴可以在命令行提示下通过下面的命令运行该程序
python hello.py python hello.py
对于使用Linux或macOS的小伙伴可以打开终端并键入下面的命令来运行程序
python3 hello.py
""" """
print('hello, world!') print('hello, world!')

View File

@ -5,7 +5,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27 Date: 2018-02-27
""" """
import math import math
radius = float(input('请输入圆的半径: ')) radius = float(input('请输入圆的半径: '))

View File

@ -1,10 +1,10 @@
""" """
百分制成绩转等级制成绩 百分制成绩转等级制成绩
90分以上 --> A 90分以上输出A
80~89 --> B 80~89输出B
70~79 --> C 70~79输出C
60~69 --> D 60~69输出D
60分以下 --> E 60分以下输出E
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊

View File

@ -5,7 +5,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28 Date: 2018-02-28
""" """
from random import randint from random import randint
face = randint(1, 6) face = randint(1, 6)

View File

@ -6,7 +6,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28 Date: 2018-02-28
""" """
import math import math
a = float(input('a = ')) a = float(input('a = '))

View File

@ -5,7 +5,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28 Date: 2018-02-28
""" """
# import getpass # import getpass
# from getpass import getpass # from getpass import getpass
# from getpass import * # from getpass import *

View File

@ -8,6 +8,5 @@ Date: 2018-03-01
sum = 0 sum = 0
for x in range(1, 101): for x in range(1, 101):
if x % 2 == 0: sum += x
sum += x
print(sum) print(sum)

View File

@ -5,7 +5,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01 Date: 2018-03-01
""" """
from math import sqrt from math import sqrt
num = int(input('请输入一个正整数: ')) num = int(input('请输入一个正整数: '))

View File

@ -6,8 +6,7 @@ Author: 骆昊
Date: 2018-03-01 Date: 2018-03-01
""" """
sum = 0 sum, num = 0, 2
num = 2
while num <= 100: while num <= 100:
sum += num sum += num
num += 2 num += 2

View File

@ -13,5 +13,3 @@ for x in range(0, 20):
z = 100 - x - y z = 100 - x - y
if 5 * x + 3 * y + z / 3 == 100: if 5 * x + 3 * y + z / 3 == 100:
print('公鸡: %d只, 母鸡: %d只, 小鸡: %d' % (x, y, z)) print('公鸡: %d只, 母鸡: %d只, 小鸡: %d' % (x, y, z))
# 要理解程序背后的算法 - 穷举法

View File

@ -11,7 +11,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-02 Date: 2018-03-02
""" """
from random import randint from random import randint
money = 1000 money = 1000

View File

@ -10,5 +10,5 @@ Date: 2018-03-02
a = 0 a = 0
b = 1 b = 1
for _ in range(20): for _ in range(20):
(a, b) = (b, a + b) a, b = b, a + b
print(a, end=' ') print(a, end=' ')

View File

@ -7,7 +7,6 @@ Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-02 Date: 2018-03-02
""" """
import random import random
answer = random.randint(1, 100) answer = random.randint(1, 100)

View File

@ -10,7 +10,6 @@ Date: 2018-03-02
import time import time
import math import math
start = time.clock()
for num in range(1, 10000): for num in range(1, 10000):
sum = 0 sum = 0
for factor in range(1, int(math.sqrt(num)) + 1): for factor in range(1, int(math.sqrt(num)) + 1):
@ -20,7 +19,3 @@ for num in range(1, 10000):
sum += num / factor sum += num / factor
if sum == num: if sum == num:
print(num) print(num)
end = time.clock()
print("执行时间:", (end - start), "")
# 通过比较上面两种不同的解决方案的执行时间 意识到优化程序的重要性

View File

@ -28,7 +28,7 @@ class Student(object):
if self.age < 18: if self.age < 18:
print('%s只能观看《熊出没》.' % self.name) print('%s只能观看《熊出没》.' % self.name)
else: else:
print('%s正在观看岛国爱情动作片.' % self.name) print('%s正在观看岛国大电影.' % self.name)
def main(): def main():

Some files were not shown because too many files have changed in this diff Show More