Merge branch 'jackfrued:master' into master
|
@ -10,33 +10,31 @@
|
|||
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版本中。
|
||||
|
||||
目前我们使用的Python 3.7.x的版本是在2018年发布的,Python的版本号分为三段,形如A.B.C。其中A表示大版本号,一般当整体重写,或出现不向后兼容的改变时,增加A;B表示功能更新,出现新功能时增加B;C表示小的改动(例如:修复了某个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表示大版本号,一般当整体重写,或出现不向后兼容的改变时,增加A;B表示功能更新,出现新功能时增加B;C表示小的改动(例如:修复了某个Bug),只要有修改就增加C。如果对Python的历史感兴趣,可以阅读名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的网络文章。
|
||||
|
||||
#### Python的优缺点
|
||||
|
||||
Python的优点很多,简单的可以总结为以下几点。
|
||||
|
||||
1. 简单和明确,做一件事只有一种方法。
|
||||
2. 学习曲线低,跟其他很多语言相比,Python更容易上手。
|
||||
3. 开放源代码,拥有强大的社区和生态圈。
|
||||
4. 解释型语言,天生具有平台可移植性。
|
||||
5. 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
|
||||
6. 可扩展性和可嵌入性,例如在Python中可以调用C/C++代码。
|
||||
7. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
|
||||
1. 简单明了,学习曲线低,比很多编程语言都容易上手。
|
||||
2. 开放源代码,拥有强大的社区和生态圈,尤其是在数据分析和机器学习领域。
|
||||
3. 解释型语言,天生具有平台可移植性,代码可以工作于不同的操作系统。
|
||||
4. 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
|
||||
5. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
|
||||
|
||||
Python的缺点主要集中在以下几点。
|
||||
|
||||
1. 执行效率稍低,因此计算密集型任务可以由C/C++编写。
|
||||
1. 执行效率稍低,对执行效率要求高的部分可以由其他语言(如:C、C++)编写。
|
||||
2. 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被弱化。
|
||||
3. 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
|
||||
|
||||
#### Python的应用领域
|
||||
|
||||
目前Python在Web应用开发、云基础设施、DevOps、网络数据采集(爬虫)、数据分析挖掘、机器学习等领域都有着广泛的应用,因此也产生了Web后端开发、数据接口开发、自动化运维、自动化测试、科学计算和可视化、数据分析、量化交易、机器人开发、自然语言处理、图像识别等一系列相关的职位。
|
||||
目前Python在Web应用后端开发、云基础设施建设、DevOps、网络数据采集(爬虫)、自动化测试、数据分析、机器学习等领域都有着广泛的应用。
|
||||
|
||||
### 安装Python解释器
|
||||
|
||||
想要开始Python编程之旅,首先得在自己使用的计算机上安装Python解释器环境,下面将以安装官方的Python解释器为例,讲解如何在不同的操作系统上安装Python环境。官方的Python解释器是用C语言实现的,也是使用最为广泛的Python解释器,通常称之为CPython。除此之外,Python解释器还有Java语言实现的Jython、C#语言实现的IronPython以及PyPy、Brython、Pyston等版本,我们暂时不对这些内容进行介绍,有兴趣的读者可以自行了解。
|
||||
想要开始Python编程之旅,首先得在自己使用的计算机上安装Python解释器环境,下面将以安装官方的Python解释器为例,讲解如何在不同的操作系统上安装Python环境。官方的Python解释器是用C语言实现的,也是使用最为广泛的Python解释器,通常称之为CPython。除此之外,Python解释器还有Java语言实现的Jython、C#语言实现的IronPython以及PyPy、Brython、Pyston等版本,有兴趣的读者可以自行了解。
|
||||
|
||||
#### Windows环境
|
||||
|
||||
|
@ -57,15 +55,15 @@ yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-devel sqlit
|
|||
2. 下载Python源代码并解压缩到指定目录。
|
||||
|
||||
```Shell
|
||||
wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz
|
||||
xz -d Python-3.7.3.tar.xz
|
||||
tar -xvf Python-3.7.3.tar
|
||||
wget https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tar.xz
|
||||
xz -d Python-3.7.6.tar.xz
|
||||
tar -xvf Python-3.7.6.tar
|
||||
```
|
||||
|
||||
3. 切换至Python源代码目录并执行下面的命令进行配置和安装。
|
||||
|
||||
```Shell
|
||||
cd Python-3.7.3
|
||||
cd Python-3.7.6
|
||||
./configure --prefix=/usr/local/python37 --enable-optimizations
|
||||
make && make install
|
||||
```
|
||||
|
@ -104,13 +102,13 @@ macOS也自带了Python 2.x版本,可以通过[Python的官方网站](https://
|
|||
```Shell
|
||||
python --version
|
||||
```
|
||||
或者是在Linux或macOS系统的终端中键入下面的命令。
|
||||
在Linux或macOS系统的终端中键入下面的命令。
|
||||
|
||||
```Shell
|
||||
python3 --version
|
||||
```
|
||||
|
||||
当然也可以先输入python或python3进入交互式环境,再执行以下的代码检查Python的版本。
|
||||
当然也可以先输入`python`或`python3`进入交互式环境,再执行以下的代码检查Python的版本。
|
||||
|
||||
```Python
|
||||
import sys
|
||||
|
@ -156,12 +154,8 @@ python3 hello.py
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
print('hello, world!')
|
||||
# print("你好,世界!")
|
||||
print('你好', '世界')
|
||||
print('hello', 'world', sep=', ', end='!')
|
||||
print('goodbye, world', end='!\n')
|
||||
# print("你好, 世界!")
|
||||
```
|
||||
|
||||
### Python开发工具
|
||||
|
@ -174,7 +168,7 @@ IDLE是安装Python环境时自带的集成开发工具,如下图所示。但
|
|||
|
||||
#### IPython - 更好的交互式编程工具
|
||||
|
||||
IPython是一种基于Python的交互式解释器。相较于原生的Python交互式环境,IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython和Jupyter,具体的操作如下所示。
|
||||
IPython是一种基于Python的交互式解释器。相较于原生的Python交互式环境,IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython,具体的操作如下所示。
|
||||
|
||||
```Shell
|
||||
pip install ipython
|
||||
|
@ -220,7 +214,7 @@ pip3 install ipython
|
|||
- Python PEP8 Autoformat - PEP8规范自动格式化插件。
|
||||
- ConvertToUTF8 - 将本地编码转换为UTF-8。
|
||||
|
||||
> 说明:事实上[Visual Studio Code](<https://code.visualstudio.com/>)可能是更好的选择,它不用花钱并提供了更为完整和强大的功能,有兴趣的读者可以自行研究。
|
||||
> **说明**:事实上[Visual Studio Code](<https://code.visualstudio.com/>)可能是更好的选择,它不用花钱并提供了更为完整和强大的功能,有兴趣的读者可以自行研究。
|
||||
|
||||
#### PyCharm - Python开发神器
|
||||
|
||||
|
@ -236,12 +230,11 @@ PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)
|
|||
import this
|
||||
```
|
||||
|
||||
> 说明:输入上面的代码,在Python的交互式环境中可以看到Tim Peter撰写的[“Python之禅”](../Python之禅.md),里面讲述的道理不仅仅适用于Python,也适用于其他编程语言。
|
||||
>
|
||||
> **说明**:输入上面的代码,在Python的交互式环境中可以看到Tim Peter撰写的[“Python之禅”](../Python之禅.md),里面讲述的道理不仅仅适用于Python,也适用于其他编程语言。
|
||||
|
||||
2. 学习使用turtle在屏幕上绘制图形。
|
||||
|
||||
> 说明:turtle是Python内置的一个非常有趣的模块,特别适合对计算机程序设计进行初体验的小伙伴,它最早是Logo语言的一部分,Logo语言是Wally Feurzig和Seymour Papert在1966发明的编程语言。
|
||||
> **说明**:turtle是Python内置的一个非常有趣的模块,特别适合对计算机程序设计进行初体验的小伙伴,它最早是Logo语言的一部分,Logo语言是Wally Feurzig和Seymour Papert在1966发明的编程语言。
|
||||
|
||||
```Python
|
||||
import turtle
|
||||
|
@ -260,4 +253,4 @@ PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)
|
|||
turtle.mainloop()
|
||||
```
|
||||
|
||||
> 提示:本章提供的代码中还有画国旗和画小猪佩奇的代码,有兴趣的读者请自行研究。
|
||||
> **提示**:本章提供的代码中还有画国旗和画小猪佩奇的代码,有兴趣的读者请自行研究。
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
|
||||
计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们大多数时候使用的计算机,虽然它们的元器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](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向全世界发布了首款商业化量子计算机。
|
||||
> **说明**:近期关于**量子计算机**的研究已经被推倒了风口浪尖,量子计算机基于量子力学进行运算,使用量子瞬移的方式来传递信息。2018年6月,Intel宣布开发出新款量子芯片并通过了在接近绝对零度环境下的测试;2019年,IBM和Google都推出了自己的量子计算机。
|
||||
|
||||
### 变量和类型
|
||||
|
||||
在程序设计中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取和修改,这是所有计算和控制的基础。计算机能处理的数据有很多种类型,除了数值之外还可以处理文本、图形、音频、视频等各种各样的数据,那么不同的数据就需要定义不同的存储类型。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`)。
|
||||
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
|
||||
- 布尔型:布尔值只有`True`、`False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True`、`False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。
|
||||
- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的`i`换成了`j`。实际上,这个类型并不能算作常用类型,大家了解下就可以了。
|
||||
- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的`i`换成了`j`。实际上,这个类型并不常用,大家了解一下就可以了。
|
||||
|
||||
#### 变量命名
|
||||
|
||||
|
@ -37,21 +37,17 @@
|
|||
|
||||
```Python
|
||||
"""
|
||||
使用变量保存数据并进行算术运算
|
||||
使用变量保存数据并进行加减乘除运算
|
||||
|
||||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
a = 321
|
||||
b = 123
|
||||
print(a + b)
|
||||
print(a - b)
|
||||
print(a * b)
|
||||
print(a / b)
|
||||
print(a // b)
|
||||
print(a % b)
|
||||
print(a ** b)
|
||||
b = 12
|
||||
print(a + b) # 333
|
||||
print(a - b) # 309
|
||||
print(a * b) # 3852
|
||||
print(a / b) # 26.75
|
||||
```
|
||||
|
||||
在Python中可以使用`type`函数对变量的类型进行检查。程序设计中函数的概念跟数学上函数的概念是一致的,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解这个概念也不要紧,我们会在后续的章节中专门讲解函数的定义和使用。
|
||||
|
@ -62,19 +58,17 @@ print(a ** b)
|
|||
|
||||
Version: 0.1
|
||||
Author: 骆昊
|
||||
Date: 2018-02-27
|
||||
"""
|
||||
|
||||
a = 100
|
||||
b = 12.345
|
||||
c = 1 + 5j
|
||||
d = 'hello, world'
|
||||
e = True
|
||||
print(type(a)) # <class 'int'>
|
||||
print(type(b)) # <class 'float'>
|
||||
print(type(c)) # <class 'complex'>
|
||||
print(type(d)) # <class 'str'>
|
||||
print(type(e)) # <class 'bool'>
|
||||
print(type(a)) # <class 'int'>
|
||||
print(type(b)) # <class 'float'>
|
||||
print(type(c)) # <class 'complex'>
|
||||
print(type(d)) # <class 'str'>
|
||||
print(type(e)) # <class 'bool'>
|
||||
```
|
||||
|
||||
可以使用Python中内置的函数对变量类型进行转换。
|
||||
|
@ -96,7 +90,6 @@ print(type(e)) # <class 'bool'>
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
a = int(input('a = '))
|
||||
b = int(input('b = '))
|
||||
print('%d + %d = %d' % (a, b, a + b))
|
||||
|
@ -133,7 +126,9 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
|
|||
|
||||
>**说明:** 在实际开发中,如果搞不清楚运算符的优先级,可以使用括号来确保运算的执行顺序。
|
||||
|
||||
下面的例子演示了赋值运算符和复合赋值运算符的使用。
|
||||
#### 赋值运算符
|
||||
|
||||
赋值运算符应该是最为常见的运算符,它的作用是将右边的值赋给左边的变量。下面的例子演示了赋值运算符和复合赋值运算符的使用。
|
||||
|
||||
```Python
|
||||
"""
|
||||
|
@ -142,40 +137,42 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
a = 10
|
||||
b = 3
|
||||
a += b # 相当于:a = a + b
|
||||
a *= a + 2 # 相当于:a = a * (a + 2)
|
||||
print(a) # 想想这里会输出什么
|
||||
a += b # 相当于:a = a + b
|
||||
a *= a + 2 # 相当于:a = a * (a + 2)
|
||||
print(a) # 算一下这里会输出什么
|
||||
```
|
||||
|
||||
下面的例子演示了比较运算符(关系运算符)、逻辑运算符和身份运算符的使用。
|
||||
### 比较运算符和逻辑运算符
|
||||
|
||||
比较运算符有的地方也称为关系运算符,包括`==`、`!=`、`<`、`>`、`<=`、`>=`,我相信没有什么好解释的,大家一看就能懂,唯一需要提醒的是比较相等用的是`==`,请注意这个地方是两个等号,因为`=`是赋值运算符,我们在上面刚刚讲到过,`==`才是比较相等的比较运算符。比较运算符会产生布尔值,要么是`True`要么是`False`。
|
||||
|
||||
逻辑运算符有三个,分别是`and`、`or`和`not`。`and`字面意思是“而且”,所以`and`运算符会连接两个布尔值,如果两个布尔值都是`True`,那么运算的结果就是`True`;左右两边的布尔值有一个是`False`,最终的运算结果就是`False`。相信大家已经想到了,如果`and`左边的布尔值是`False`,不管右边的布尔值是什么,最终的结果都是`False`,所以在做运算的时候右边的值会被跳过(短路处理),这也就意味着在`and`运算符左边为`False`的情况下,右边的表达式根本不会执行。`or`字面意思是“或者”,所以`or`运算符也会连接两个布尔值,如果两个布尔值有任意一个是`True`,那么最终的结果就是`True`。当然,`or`运算符也是有短路功能的,在它左边的布尔值为`True`的情况下,右边的表达式根本不会执行。`not`运算符的后面会跟上一个布尔值,它的作用是得到与该布尔值相反的值,也就是说,后面的布尔值如果是`True`运算结果就是`False`,而后面的布尔值如果是`False`则运算结果就是`True`。
|
||||
|
||||
```Python
|
||||
"""
|
||||
比较、逻辑和算身份运算符的使用
|
||||
比较运算符和逻辑运算符的使用
|
||||
|
||||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
flag0 = 1 == 1
|
||||
flag1 = 3 > 2
|
||||
flag2 = 2 < 1
|
||||
flag3 = flag1 and flag2
|
||||
flag4 = flag1 or flag2
|
||||
flag5 = not (1 != 2)
|
||||
print('flag0 =', flag0) # flag0 = True
|
||||
print('flag1 =', flag1) # flag1 = True
|
||||
print('flag2 =', flag2) # flag2 = False
|
||||
print('flag3 =', flag3) # flag3 = False
|
||||
print('flag4 =', flag4) # flag4 = True
|
||||
print('flag5 =', flag5) # flag5 = False
|
||||
print(flag1 is True) # True
|
||||
print(flag2 is not False) # False
|
||||
print('flag0 =', flag0) # flag0 = True
|
||||
print('flag1 =', flag1) # flag1 = True
|
||||
print('flag2 =', flag2) # flag2 = False
|
||||
print('flag3 =', flag3) # flag3 = False
|
||||
print('flag4 =', flag4) # flag4 = True
|
||||
print('flag5 =', flag5) # flag5 = False
|
||||
```
|
||||
|
||||
> **说明**:比较运算符的优先级高于赋值运算符,所以`flag0 = 1 == 1`先做`1 == 1`产生布尔值`True`,再将这个值赋值给变量`flag0`。`print`函数可以输出多个值,多个值之间可以用`,`进行分隔,输出的内容之间默认以空格分开。
|
||||
|
||||
### 练习
|
||||
|
||||
#### 练习1:华氏温度转换为摄氏温度。
|
||||
|
@ -191,12 +188,17 @@ print(flag2 is not False) # False
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
f = float(input('请输入华氏温度: '))
|
||||
c = (f - 32) / 1.8
|
||||
print('%.1f华氏度 = %.1f摄氏度' % (f, c))
|
||||
```
|
||||
|
||||
> **说明**:在使用`print`函数输出时,也可以对字符串内容进行格式化处理,上面`print`函数中的字符串`%1.f`是一个占位符,稍后会由一个`float`类型的变量值替换掉它。同理,如果字符串中有`%d`,后面可以用一个`int`类型的变量值替换掉它,而`%s`会被字符串的值替换掉。除了这种格式化字符串的方式外,还可以用下面的方式来格式化字符串,其中`{f:.1f}`和`{c:.1f}`可以先看成是`{f}`和`{c}`,表示输出时会用变量`f`和变量`c`的值替换掉这两个占位符,后面的`:.1f`表示这是一个浮点数,小数点后保留1位有效数字。
|
||||
>
|
||||
> ```Python
|
||||
> print(f'{f:.1f}华氏度 = {c:.1f}摄氏度')
|
||||
> ```
|
||||
|
||||
#### 练习2:输入圆的半径计算计算周长和面积。
|
||||
|
||||
参考答案:
|
||||
|
@ -208,12 +210,9 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c))
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
radius = float(input('请输入圆的半径: '))
|
||||
perimeter = 2 * math.pi * radius
|
||||
area = math.pi * radius * radius
|
||||
perimeter = 2 * 3.1416 * radius
|
||||
area = 3.1416 * radius * radius
|
||||
print('周长: %.2f' % perimeter)
|
||||
print('面积: %.2f' % area)
|
||||
```
|
||||
|
@ -229,11 +228,11 @@ print('面积: %.2f' % area)
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
year = int(input('请输入年份: '))
|
||||
# 如果代码太长写成一行不便于阅读 可以使用\对代码进行折行
|
||||
is_leap = (year % 4 == 0 and year % 100 != 0) or \
|
||||
year % 400 == 0
|
||||
is_leap = year % 4 == 0 and year % 100 != 0 or \
|
||||
year % 400 == 0
|
||||
print(is_leap)
|
||||
```
|
||||
|
||||
> **说明**:比较运算符会产生布尔值,而逻辑运算符`and`和`or`会对这些布尔值进行组合,最终也是得到一个布尔值,闰年输出`True`,平年输出`False`。
|
|
@ -15,7 +15,6 @@
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
username = input('请输入用户名: ')
|
||||
password = input('请输入口令: ')
|
||||
# 用户名是admin且密码是123456则身份验证成功否则身份验证失败
|
||||
|
@ -25,9 +24,9 @@ else:
|
|||
print('身份验证失败!')
|
||||
```
|
||||
|
||||
唯一需要说明的是和C/C++、Java等语言不同,Python中没有用花括号来构造代码块而是使用了缩进的方式来设置代码的层次结构,如果`if`条件成立的情况下需要执行多条语句,只要保持多条语句具有相同的缩进就可以了,换句话说连续的代码如果又保持了相同的缩进那么它们属于同一个代码块,相当于是一个执行的整体。
|
||||
需要说明的是和C/C++、Java等语言不同,Python中没有用花括号来构造代码块而是**使用了缩进的方式来表示代码的层次结构**,如果`if`条件成立的情况下需要执行多条语句,只要保持多条语句具有相同的缩进就可以了。换句话说**连续的代码如果又保持了相同的缩进那么它们属于同一个代码块**,相当于是一个执行的整体。**缩进**可以使用任意数量的空格,但**通常使用4个空格**,建议大家**不要使用制表键**或者**设置你的代码编辑工具自动将制表键变成4个空格**。
|
||||
|
||||
当然如果要构造出更多的分支,可以使用`if…elif…else…`结构,例如下面的分段函数求值。
|
||||
当然如果要构造出更多的分支,可以使用`if...elif...else...`结构或者嵌套的`if...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}$$](./res/formula_1.png)
|
||||
|
||||
|
@ -92,7 +91,6 @@ print('f(%.2f) = %.2f' % (x, y))
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
value = float(input('请输入长度: '))
|
||||
unit = input('请输入单位: ')
|
||||
if unit == 'in' or unit == '英寸':
|
||||
|
@ -116,7 +114,6 @@ else:
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
score = float(input('请输入成绩: '))
|
||||
if score >= 90:
|
||||
grade = 'A'
|
||||
|
@ -141,7 +138,6 @@ print('对应的等级是:', grade)
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
a = float(input('a = '))
|
||||
b = float(input('b = '))
|
||||
c = float(input('c = '))
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
### 应用场景
|
||||
|
||||
如果在程序中我们需要重复的执行某条或某些指令,例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了,刚才的描述中不仅仅有需要重复的动作,还需要用到上一章讲的分支结构。再举一个简单的例子,我们要实现一个每隔1秒中在屏幕上打印一次"hello, world"并持续打印一个小时的程序,我们肯定不能够直接把`print('hello, world')`这句代码写3600遍,如果真的要这样做,那么编程的工作就太无聊乏味了。因此,我们还需要了解一下循环结构,有了循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的去执行。
|
||||
我们在写程序的时候,一定会遇到需要重复执行某条或某些指令的场景。例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向移动的指令。在这个场景中,让机器人向球门方向移动就是一个需要重复的动作,当然这里还会用到上一课讲的分支结构来判断机器人是否持球以及是否进入射门范围。再举一个简单的例子,如果要实现每隔1秒中在屏幕上打印一次“hello, world”并持续打印一个小时,我们肯定不能够直接把`print('hello, world')`这句代码写3600遍,这里同样需要循环结构。
|
||||
|
||||
在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。
|
||||
循环结构就是程序中控制某条或某些指令重复执行的结构。在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。
|
||||
|
||||
### for-in循环
|
||||
|
||||
|
@ -24,11 +24,12 @@ for x in range(101):
|
|||
print(sum)
|
||||
```
|
||||
|
||||
需要说明的是上面代码中的`range(101)`可以用来构造一个从0到100的取值范围,这样就可以构造出一个整数的序列并用于循环中,例如:
|
||||
需要说明的是上面代码中的`range(1, 101)`可以用来构造一个从1到100的范围,当我们把这样一个范围放到`for-in`循环中,就可以通过前面的循环变量`x`依次取出从1到100的整数。当然,`range`的用法非常灵活,下面给出了一个例子:
|
||||
|
||||
- `range(101)`可以产生一个0到100的整数序列。
|
||||
- `range(1, 100)`可以产生一个1到99的整数序列。
|
||||
- `range(1, 100, 2)`可以产生一个1到99的奇数序列,其中2是步长,即数值序列的增量。
|
||||
- `range(101)`:可以用来产生0到100范围的整数,需要注意的是取不到101。
|
||||
- `range(1, 101)`:可以用来产生1到100范围的整数,相当于前面是闭区间后面是开区间。
|
||||
- `range(1, 101, 2)`:可以用来产生1到100的奇数,其中2是步长,即每次数值递增的值。
|
||||
- `range(100, 0, -2)`:可以用来产生100到1的偶数,其中-2是步长,即每次数字递减的值。
|
||||
|
||||
知道了这一点,我们可以用下面的代码来实现1~100之间的偶数求和。
|
||||
|
||||
|
@ -46,7 +47,7 @@ for x in range(2, 101, 2):
|
|||
print(sum)
|
||||
```
|
||||
|
||||
也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。
|
||||
当然,也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。
|
||||
|
||||
```Python
|
||||
"""
|
||||
|
@ -63,20 +64,21 @@ for x in range(1, 101):
|
|||
print(sum)
|
||||
```
|
||||
|
||||
> **说明**:相较于上面直接跳过奇数的做法,下面这种做法很明显并不是很好的选择。
|
||||
|
||||
### while循环
|
||||
|
||||
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环。`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`循环继续,表达式的值为`False`循环结束。下面我们通过一个“猜数字”的小游戏(计算机出一个1~100之间的随机数,人输入自己猜的数字,计算机给出对应的提示信息,直到人猜出计算机出的数字)来看看如何使用`while`循环。
|
||||
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环。`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`则继续循环;表达式的值为`False`则结束循环。
|
||||
|
||||
下面我们通过一个“猜数字”的小游戏来看看如何使用`while`循环。猜数字游戏的规则是:计算机出一个1到100之间的随机数,玩家输入自己猜的数字,计算机给出对应的提示信息(大一点、小一点或猜对了),如果玩家猜中了数字,计算机提示用户一共猜了多少次,游戏结束,否则游戏继续。
|
||||
|
||||
```Python
|
||||
"""
|
||||
猜数字游戏
|
||||
计算机出一个1~100之间的随机数由人来猜
|
||||
计算机根据人猜的数字分别给出提示大一点/小一点/猜对了
|
||||
|
||||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
import random
|
||||
|
||||
answer = random.randint(1, 100)
|
||||
|
@ -147,6 +149,8 @@ else:
|
|||
|
||||
#### 练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。
|
||||
|
||||
> **提示**:两个数的最大公约数是两个数的公共因子中最大的那个数;两个数的最小公倍数则是能够同时被两个数整除的最小的那个数。
|
||||
|
||||
参考答案:
|
||||
|
||||
```Python
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
|
||||
m = int(input('m = '))
|
||||
n = int(input('n = '))
|
||||
fm = 1
|
||||
|
@ -26,10 +25,10 @@ for num in range(1, m + 1):
|
|||
fn = 1
|
||||
for num in range(1, n + 1):
|
||||
fn *= num
|
||||
fmn = 1
|
||||
fm_n = 1
|
||||
for num in range(1, m - n + 1):
|
||||
fmn *= num
|
||||
print(fm // fn // fmn)
|
||||
fm_n *= num
|
||||
print(fm // fn // fm_n)
|
||||
```
|
||||
|
||||
### 函数的作用
|
||||
|
@ -43,7 +42,13 @@ print(fm // fn // fmn)
|
|||
在了解了如何定义函数后,我们可以对上面的代码进行重构,所谓重构就是在不影响代码执行结果的前提下对代码的结构进行调整,重构之后的代码如下所示。
|
||||
|
||||
```Python
|
||||
def factorial(num):
|
||||
"""
|
||||
输入M和N计算C(M,N)
|
||||
|
||||
Version: 0.1
|
||||
Author: 骆昊
|
||||
"""
|
||||
def fac(num):
|
||||
"""求阶乘"""
|
||||
result = 1
|
||||
for n in range(1, num + 1):
|
||||
|
@ -54,10 +59,10 @@ def factorial(num):
|
|||
m = int(input('m = '))
|
||||
n = int(input('n = '))
|
||||
# 当需要计算阶乘的时候不用再写循环求阶乘而是直接调用已经定义好的函数
|
||||
print(factorial(m) // factorial(n) // factorial(m - n))
|
||||
print(fac(m) // fac(n) // fac(m - n))
|
||||
```
|
||||
|
||||
> **说明:** Python的`math`模块中其实已经有一个`factoria`l函数了,事实上要计算阶乘可以直接使用这个现成的函数而不用自己定义。下面例子中的一些函数在Python中也都是现成的,我们这里是为了讲解函数的定义和使用才把它们又实现了一遍,实际开发中不建议做这种低级的重复性的工作。
|
||||
> **说明:** Python的`math`模块中其实已经有一个名为`factorial`函数实现了阶乘运算,事实上求阶乘并不用自己定义函数。下面的例子中,我们讲的函数在Python标准库已经实现过了,我们这里是为了讲解函数的定义和使用才把它们又实现了一遍,**实际开发中并不建议做这种低级的重复劳动**。
|
||||
|
||||
|
||||
### 函数的参数
|
||||
|
@ -267,7 +272,7 @@ def is_palindrome(num):
|
|||
```Python
|
||||
def is_prime(num):
|
||||
"""判断一个数是不是素数"""
|
||||
for factor in range(2, num):
|
||||
for factor in range(2, int(num ** 0.5) + 1):
|
||||
if num % factor == 0:
|
||||
return False
|
||||
return True if num != 1 else False
|
||||
|
@ -286,6 +291,8 @@ if __name__ == '__main__':
|
|||
|
||||
> **注意**:通过上面的程序可以看出,当我们**将代码中重复出现的和相对独立的功能抽取成函数**后,我们可以**组合使用这些函数**来解决更为复杂的问题,这也是我们为什么要定义和使用函数的一个非常重要的原因。
|
||||
|
||||
### 变量的作用域
|
||||
|
||||
最后,我们来讨论一下Python中有关变量作用域的问题。
|
||||
|
||||
```Python
|
||||
|
@ -344,7 +351,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%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代码按照下面的格式进行书写,这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ if __name__ == '__main__':
|
|||
|
||||
### 使用元组
|
||||
|
||||
Python 中的元组与列表类似也是一种容器数据类型,可以用一个变量(对象)来存储多个数据,不同之处在于元组的元素不能修改,在前面的代码中我们已经不止一次使用过元组了。顾名思义,我们把多个元素组合到一起就形成了一个元组,所以它和列表一样可以保存多条数据。下面的代码演示了如何定义和使用元组。
|
||||
Python中的元组与列表类似也是一种容器数据类型,可以用一个变量(对象)来存储多个数据,不同之处在于元组的元素不能修改,在前面的代码中我们已经不止一次使用过元组了。顾名思义,我们把多个元素组合到一起就形成了一个元组,所以它和列表一样可以保存多条数据。下面的代码演示了如何定义和使用元组。
|
||||
|
||||
```Python
|
||||
# 定义元组
|
||||
|
@ -319,30 +319,39 @@ Python中的集合跟数学上的集合是一致的,不允许有重复元素
|
|||
|
||||
![](./res/python-set.png)
|
||||
|
||||
可以按照下面代码所示的方式来创建和使用集合。
|
||||
|
||||
```Python
|
||||
# 创建集合的字面量语法
|
||||
set1 = {1, 2, 3, 3, 3, 2}
|
||||
print(set1)
|
||||
print('Length =', len(set1))
|
||||
# 创建集合的构造器语法(面向对象部分会进行详细讲解)
|
||||
set2 = set(range(1, 10))
|
||||
print(set2)
|
||||
set3 = set((1, 2, 3, 3, 2, 1))
|
||||
print(set2, set3)
|
||||
# 创建集合的推导式语法(推导式也可以用于推导集合)
|
||||
set4 = {num for num in range(1, 100) if num % 3 == 0 or num % 5 == 0}
|
||||
print(set4)
|
||||
```
|
||||
|
||||
向集合添加元素和从集合删除元素。
|
||||
|
||||
```Python
|
||||
set1.add(4)
|
||||
set1.add(5)
|
||||
set2.update([11, 12])
|
||||
print(set1)
|
||||
print(set2)
|
||||
set2.discard(5)
|
||||
# remove的元素如果不存在会引发KeyError
|
||||
if 4 in set2:
|
||||
set2.remove(4)
|
||||
print(set2)
|
||||
# 遍历集合容器
|
||||
for elem in set2:
|
||||
print(elem ** 2, end=' ')
|
||||
print()
|
||||
# 将元组转换成集合
|
||||
set3 = set((1, 2, 3, 3, 2, 1))
|
||||
print(set1, set2)
|
||||
print(set3.pop())
|
||||
print(set3)
|
||||
```
|
||||
|
||||
集合的成员、交集、并集、差集等运算。
|
||||
|
||||
```Python
|
||||
# 集合的交集、并集、差集、对称差运算
|
||||
print(set1 & set2)
|
||||
# print(set1.intersection(set2))
|
||||
|
@ -367,16 +376,25 @@ print(set1 >= set3)
|
|||
|
||||
### 使用字典
|
||||
|
||||
字典是另一种可变容器模型,类似于我们生活中使用的字典,它可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。下面的代码演示了如何定义和使用字典。
|
||||
字典是另一种可变容器模型,Python中的字典跟我们生活中使用的字典是一样一样的,它可以存储任意类型对象,与列表、集合不同的是,字典的每个元素都是由一个键和一个值组成的“键值对”,键和值通过冒号分开。下面的代码演示了如何定义和使用字典。
|
||||
|
||||
```Python
|
||||
# 创建字典的字面量语法
|
||||
scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}
|
||||
print(scores)
|
||||
# 创建字典的构造器语法
|
||||
items1 = dict(one=1, two=2, three=3, four=4)
|
||||
# 通过zip函数将两个序列压成字典
|
||||
items2 = dict(zip(['a', 'b', 'c'], '123'))
|
||||
# 创建字典的推导式语法
|
||||
items3 = {num: num ** 2 for num in range(1, 10)}
|
||||
print(items1, items2, items3)
|
||||
# 通过键可以获取字典中对应的值
|
||||
print(scores['骆昊'])
|
||||
print(scores['狄仁杰'])
|
||||
# 对字典进行遍历(遍历的其实是键再通过键取对应的值)
|
||||
for elem in scores:
|
||||
print('%s\t--->\t%d' % (elem, scores[elem]))
|
||||
# 对字典中所有键值对进行遍历
|
||||
for key in scores:
|
||||
print(f'{key}: {scores[key]}')
|
||||
# 更新字典中的元素
|
||||
scores['白元芳'] = 65
|
||||
scores['诸葛王朗'] = 71
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
| \| | 分支 | foo\|bar | 可以匹配foo或者bar |
|
||||
| (?#) | 注释 | | |
|
||||
| (exp) | 匹配exp并捕获到自动命名的组中 | | |
|
||||
| (? <name>exp) | 匹配exp并捕获到名为name的组中 | | |
|
||||
| (?<name>exp) | 匹配exp并捕获到名为name的组中 | | |
|
||||
| (?:exp) | 匹配exp但是不捕获匹配的文本 | | |
|
||||
| (?=exp) | 匹配exp前面的位置 | \\b\\w+(?=ing) | 可以匹配I'm dancing中的danc |
|
||||
| (?<=exp) | 匹配exp后面的位置 | (?<=\\bdanc)\\w+\\b | 可以匹配I love dancing and reading中的第一个ing |
|
||||
|
|
|
@ -316,7 +316,7 @@ if __name__ == '__main__':
|
|||
|
||||
但是,切换作业是有代价的,比如从语文切到数学,要先收拾桌子上的语文书本、钢笔(这叫保存现场),然后,打开数学课本、找出圆规直尺(这叫准备新环境),才能开始做数学作业。操作系统在切换进程或者线程时也是一样的,它需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假死状态。所以,多任务一旦多到一个限度,反而会使得系统性能急剧下降,最终导致所有任务都做不好。
|
||||
|
||||
是否采用多任务的第二个考虑是任务的类型,可以把任务分为计算密集型和I/O密集型。计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如对视频进行编码解码或者格式转换等等,这种任务全靠CPU的运算能力,虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低。计算密集型任务由于主要消耗CPU资源,这类任务用Python这样的脚本语言去执行效率通常很低,最能胜任这类任务的是C语言,我们之前提到了Python中有嵌入C/C++代码的机制。
|
||||
是否采用多任务的第二个考虑是任务的类型,可以把任务分为计算密集型和I/O密集型。计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如对视频进行编码解码或者格式转换等等,这种任务全靠CPU的运算能力,虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低。计算密集型任务由于主要消耗CPU资源,这类任务用Python这样的脚本语言去执行效率通常很低,最能胜任这类任务的是C语言,我们之前提到过Python中有嵌入C/C++代码的机制。
|
||||
|
||||
除了计算密集型任务,其他的涉及到网络、存储介质I/O的任务都可以视为I/O密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待I/O操作完成(因为I/O的速度远远低于CPU和内存的速度)。对于I/O密集型任务,如果启动多任务,就可以减少I/O等待时间从而让CPU高效率的运转。有一大类的任务都属于I/O密集型任务,这其中包括了我们很快会涉及到的网络应用和Web应用。
|
||||
|
||||
|
@ -324,9 +324,9 @@ if __name__ == '__main__':
|
|||
|
||||
### 单线程+异步I/O
|
||||
|
||||
现代操作系统对I/O操作的改进中最为重要的就是支持异步I/O。如果充分利用操作系统提供的异步I/O支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型。Nginx就是支持异步I/O的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。用Node.js开发的服务器端程序也使用了这种工作模式,这也是当下实现多任务编程的一种趋势。
|
||||
现代操作系统对I/O操作的改进中最为重要的就是支持异步I/O。如果充分利用操作系统提供的异步I/O支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型。Nginx就是支持异步I/O的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。用Node.js开发的服务器端程序也使用了这种工作模式,这也是当下并发编程的一种流行方案。
|
||||
|
||||
在Python语言中,单线程+异步I/O的编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。协程最大的优势就是极高的执行效率,因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销。协程的第二个优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不用加锁,只需要判断状态就好了,所以执行效率比多线程高很多。如果想要充分利用CPU的多核特性,最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。关于这方面的内容,我稍后会做一个专题来进行讲解。
|
||||
在Python语言中,单线程+异步I/O的编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。协程最大的优势就是极高的执行效率,因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销。协程的第二个优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不用加锁,只需要判断状态就好了,所以执行效率比多线程高很多。如果想要充分利用CPU的多核特性,最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。关于这方面的内容,在后续的课程中会进行讲解。
|
||||
|
||||
### 应用案例
|
||||
|
||||
|
|
|
@ -110,13 +110,70 @@ Pillow中最为重要的是Image类,读取和处理图像都要通过这个类
|
|||
|
||||
### 处理Excel电子表格
|
||||
|
||||
Python的openpyxl模块让我们可以在Python程序中读取和修改Excel电子表格,当然实际工作中,我们可能会用LibreOffice Calc和OpenOffice Calc来处理Excel的电子表格文件,这就意味着openpyxl模块也能处理来自这些软件生成的电子表格。关于openpyxl的使用手册和使用文档可以查看它的[官方文档](https://openpyxl.readthedocs.io/en/stable/#)。
|
||||
Python的openpyxl模块让我们可以在Python程序中读取和修改Excel电子表格,由于微软从Office 2007开始使用了新的文件格式,这使得Office Excel和LibreOffice Calc、OpenOffice Calc是完全兼容的,这就意味着openpyxl模块也能处理来自这些软件生成的电子表格。
|
||||
|
||||
```Python
|
||||
import datetime
|
||||
|
||||
from openpyxl import Workbook
|
||||
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
|
||||
ws['A1'] = 42
|
||||
ws.append([1, 2, 3])
|
||||
ws['A2'] = datetime.datetime.now()
|
||||
|
||||
wb.save("sample.xlsx")
|
||||
```
|
||||
|
||||
### 处理Word文档
|
||||
|
||||
利用python-docx模块,Pytho 可以创建和修改Word文档,当然这里的Word文档不仅仅是指通过微软的Office软件创建的扩展名为docx的文档,LibreOffice Writer和OpenOffice Writer都是免费的字处理软件。
|
||||
利用python-docx模块,Python可以创建和修改Word文档,当然这里的Word文档不仅仅是指通过微软的Office软件创建的扩展名为docx的文档,LibreOffice Writer和OpenOffice Writer都是免费的字处理软件。
|
||||
|
||||
```Python
|
||||
from docx import Document
|
||||
from docx.shared import Inches
|
||||
|
||||
### 处理PDF文档
|
||||
document = Document()
|
||||
|
||||
PDF是Portable Document Format的缩写,使用.pdf作为文件扩展名。接下来我们就研究一下如何通过Python实现从PDF读取文本内容和从已有的文档生成新的PDF文件。
|
||||
document.add_heading('Document Title', 0)
|
||||
|
||||
p = document.add_paragraph('A plain paragraph having some ')
|
||||
p.add_run('bold').bold = True
|
||||
p.add_run(' and some ')
|
||||
p.add_run('italic.').italic = True
|
||||
|
||||
document.add_heading('Heading, level 1', level=1)
|
||||
document.add_paragraph('Intense quote', style='Intense Quote')
|
||||
|
||||
document.add_paragraph(
|
||||
'first item in unordered list', style='List Bullet'
|
||||
)
|
||||
document.add_paragraph(
|
||||
'first item in ordered list', style='List Number'
|
||||
)
|
||||
|
||||
document.add_picture('monty-truth.png', width=Inches(1.25))
|
||||
|
||||
records = (
|
||||
(3, '101', 'Spam'),
|
||||
(7, '422', 'Eggs'),
|
||||
(4, '631', 'Spam, spam, eggs, and spam')
|
||||
)
|
||||
|
||||
table = document.add_table(rows=1, cols=3)
|
||||
hdr_cells = table.rows[0].cells
|
||||
hdr_cells[0].text = 'Qty'
|
||||
hdr_cells[1].text = 'Id'
|
||||
hdr_cells[2].text = 'Desc'
|
||||
for qty, id, desc in records:
|
||||
row_cells = table.add_row().cells
|
||||
row_cells[0].text = str(qty)
|
||||
row_cells[1].text = id
|
||||
row_cells[2].text = desc
|
||||
|
||||
document.add_page_break()
|
||||
|
||||
document.save('demo.docx')
|
||||
```
|
||||
|
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 73 KiB |
|
@ -10,24 +10,23 @@ Date: 2018-03-20
|
|||
# 每个进程都有自己独立的内存空间 所以进程之间共享数据只能通过IPC的方式
|
||||
|
||||
|
||||
from multiprocessing import Process, Queue
|
||||
from multiprocessing import Process, Queue, current_process
|
||||
from time import sleep
|
||||
|
||||
|
||||
def sub_task(string, q):
|
||||
number = q.get()
|
||||
while number:
|
||||
print('%d: %s' % (number, string))
|
||||
sleep(0.001)
|
||||
number = q.get()
|
||||
def sub_task(content, counts):
|
||||
print(f'PID: {current_process().pid}')
|
||||
counter = 0
|
||||
while counter < counts:
|
||||
counter += 1
|
||||
print(f'{counter}: {content}')
|
||||
sleep(0.01)
|
||||
|
||||
|
||||
def main():
|
||||
q = Queue(10)
|
||||
for number in range(1, 11):
|
||||
q.put(number)
|
||||
Process(target=sub_task, args=('Ping', q)).start()
|
||||
Process(target=sub_task, args=('Pong', q)).start()
|
||||
number = random.randrange(5, 10)
|
||||
Process(target=sub_task, args=('Ping', number)).start()
|
||||
Process(target=sub_task, args=('Pong', number)).start()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 515 KiB After Width: | Height: | Size: 412 KiB |
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 419 B |
Before Width: | Height: | Size: 618 B After Width: | Height: | Size: 461 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1016 B |
Before Width: | Height: | Size: 816 B After Width: | Height: | Size: 683 B |
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 323 B |
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 798 B After Width: | Height: | Size: 621 B |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 169 KiB |
Before Width: | Height: | Size: 609 KiB After Width: | Height: | Size: 468 KiB |
Before Width: | Height: | Size: 546 KiB After Width: | Height: | Size: 433 KiB |
Before Width: | Height: | Size: 383 KiB After Width: | Height: | Size: 301 KiB |
Before Width: | Height: | Size: 506 KiB After Width: | Height: | Size: 414 KiB |
Before Width: | Height: | Size: 486 KiB After Width: | Height: | Size: 397 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 1012 KiB After Width: | Height: | Size: 824 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 349 KiB After Width: | Height: | Size: 268 KiB |
Before Width: | Height: | Size: 398 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 74 KiB |
|
@ -1,6 +1,6 @@
|
|||
## Web前端概述
|
||||
|
||||
> 说明:本文使用的部分插图来自*Jon Duckett*先生的*[HTML and CSS: Design and Build Websites](https://www.amazon.cn/dp/1118008189/ref=sr_1_5?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&keywords=html+%26+css&qid=1554609325&s=gateway&sr=8-5)*一书,这是一本非常棒的前端入门书,有兴趣的读者可以在亚马逊或者其他网站上找到该书的购买链接。
|
||||
> **说明**:本文使用的部分插图来自*Jon Duckett*先生的*[HTML and CSS: Design and Build Websites](https://www.amazon.cn/dp/1118008189/ref=sr_1_5?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&keywords=html+%26+css&qid=1554609325&s=gateway&sr=8-5)*一书,这是一本非常棒的前端入门书,有兴趣的读者可以在亚马逊或者其他网站上找到该书的购买链接。
|
||||
|
||||
### HTML简史
|
||||
|
||||
|
@ -288,7 +288,7 @@
|
|||
- `delete`关键字
|
||||
- 标准对象
|
||||
- `Number` / `String` / `Boolean` / `Symbol` / `Array` / `Function`
|
||||
- `Date` / `Error` / `Math` / `RegEx` / `Object` / `Map` / `Set`
|
||||
- `Date` / `Error` / `Math` / `RegExp` / `Object` / `Map` / `Set`
|
||||
- `JSON` / `Promise` / `Generator` / `Reflect` / `Proxy`
|
||||
|
||||
#### BOM
|
||||
|
@ -903,4 +903,4 @@ Bulma是一个基于Flexbox的现代化的CSS框架,其初衷就是移动优
|
|||
|
||||
3. 可视化
|
||||
|
||||
![](./res/bootstrap-layoutit.png)
|
||||
![](./res/bootstrap-layoutit.png)
|
|
@ -68,7 +68,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
<div>
|
||||
<input @keydown.enter="addItem()" type="text" id="fname" v-model="fname">
|
||||
<input @keydown.enter="addItem()" type="text" id="fname" v-model.trim="fname">
|
||||
<button id="ok" @click="addItem()">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,8 +82,8 @@
|
|||
},
|
||||
methods: {
|
||||
addItem() {
|
||||
if (this.fname.trim().length > 0) {
|
||||
this.fruits.push(this.fname.trim())
|
||||
if (this.fname.length > 0) {
|
||||
this.fruits.push(this.fname)
|
||||
}
|
||||
this.fname = ''
|
||||
},
|
||||
|
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 330 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 582 B |
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 26 KiB |