更新了前15天和最后10天的内容
parent
3351f019ed
commit
dbe54797b0
|
@ -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的整个开发过程更加透明,社区对开发进度的影响逐渐扩大,生态圈开始慢慢形成。
|
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表示大版本号,一般当整体重写,或出现不向后兼容的改变时,增加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的优缺点
|
||||||
|
|
||||||
Python的优点很多,简单的可以总结为以下几点。
|
Python的优点很多,简单的可以总结为以下几点。
|
||||||
|
|
||||||
1. 简单和明确,做一件事只有一种方法。
|
1. 简单明了,学习曲线低,比很多编程语言都容易上手。
|
||||||
2. 学习曲线低,跟其他很多语言相比,Python更容易上手。
|
2. 开放源代码,拥有强大的社区和生态圈,尤其是在数据分析和机器学习领域。
|
||||||
3. 开放源代码,拥有强大的社区和生态圈。
|
3. 解释型语言,天生具有平台可移植性,代码可以工作于不同的操作系统。
|
||||||
4. 解释型语言,天生具有平台可移植性。
|
4. 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
|
||||||
5. 对两种主流的编程范式(面向对象编程和函数式编程)都提供了支持。
|
5. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
|
||||||
6. 可扩展性和可嵌入性,例如在Python中可以调用C/C++代码。
|
|
||||||
7. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
|
|
||||||
|
|
||||||
Python的缺点主要集中在以下几点。
|
Python的缺点主要集中在以下几点。
|
||||||
|
|
||||||
1. 执行效率稍低,因此计算密集型任务可以由C/C++编写。
|
1. 执行效率稍低,对执行效率要求高的部分可以由其他语言(如:C、C++)编写。
|
||||||
2. 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被弱化。
|
2. 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被弱化。
|
||||||
3. 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
|
3. 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
|
||||||
|
|
||||||
#### Python的应用领域
|
#### Python的应用领域
|
||||||
|
|
||||||
目前Python在Web应用开发、云基础设施、DevOps、网络数据采集(爬虫)、数据分析挖掘、机器学习等领域都有着广泛的应用,因此也产生了Web后端开发、数据接口开发、自动化运维、自动化测试、科学计算和可视化、数据分析、量化交易、机器人开发、自然语言处理、图像识别等一系列相关的职位。
|
目前Python在Web应用后端开发、云基础设施建设、DevOps、网络数据采集(爬虫)、自动化测试、数据分析、机器学习等领域都有着广泛的应用。
|
||||||
|
|
||||||
### 安装Python解释器
|
### 安装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环境
|
#### Windows环境
|
||||||
|
|
||||||
|
@ -104,13 +102,13 @@ macOS也自带了Python 2.x版本,可以通过[Python的官方网站](https://
|
||||||
```Shell
|
```Shell
|
||||||
python --version
|
python --version
|
||||||
```
|
```
|
||||||
或者是在Linux或macOS系统的终端中键入下面的命令。
|
在Linux或macOS系统的终端中键入下面的命令。
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
python3 --version
|
python3 --version
|
||||||
```
|
```
|
||||||
|
|
||||||
当然也可以先输入python或python3进入交互式环境,再执行以下的代码检查Python的版本。
|
当然也可以先输入`python`或`python3`进入交互式环境,再执行以下的代码检查Python的版本。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
import sys
|
import sys
|
||||||
|
@ -156,12 +154,8 @@ python3 hello.py
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
print('hello, world!')
|
print('hello, world!')
|
||||||
# print("你好, 世界!")
|
# print("你好, 世界!")
|
||||||
print('你好', '世界')
|
|
||||||
print('hello', 'world', sep=', ', end='!')
|
|
||||||
print('goodbye, world', end='!\n')
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Python开发工具
|
### Python开发工具
|
||||||
|
@ -174,7 +168,7 @@ IDLE是安装Python环境时自带的集成开发工具,如下图所示。但
|
||||||
|
|
||||||
#### IPython - 更好的交互式编程工具
|
#### IPython - 更好的交互式编程工具
|
||||||
|
|
||||||
IPython是一种基于Python的交互式解释器。相较于原生的Python交互式环境,IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython和Jupyter,具体的操作如下所示。
|
IPython是一种基于Python的交互式解释器。相较于原生的Python交互式环境,IPython提供了更为强大的编辑和交互功能。可以通过Python的包管理工具pip安装IPython,具体的操作如下所示。
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
pip install ipython
|
pip install ipython
|
||||||
|
@ -220,7 +214,7 @@ pip3 install ipython
|
||||||
- Python PEP8 Autoformat - PEP8规范自动格式化插件。
|
- Python PEP8 Autoformat - PEP8规范自动格式化插件。
|
||||||
- ConvertToUTF8 - 将本地编码转换为UTF-8。
|
- ConvertToUTF8 - 将本地编码转换为UTF-8。
|
||||||
|
|
||||||
> 说明:事实上[Visual Studio Code](<https://code.visualstudio.com/>)可能是更好的选择,它不用花钱并提供了更为完整和强大的功能,有兴趣的读者可以自行研究。
|
> **说明**:事实上[Visual Studio Code](<https://code.visualstudio.com/>)可能是更好的选择,它不用花钱并提供了更为完整和强大的功能,有兴趣的读者可以自行研究。
|
||||||
|
|
||||||
#### PyCharm - Python开发神器
|
#### PyCharm - Python开发神器
|
||||||
|
|
||||||
|
@ -236,12 +230,11 @@ PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)
|
||||||
import this
|
import this
|
||||||
```
|
```
|
||||||
|
|
||||||
> 说明:输入上面的代码,在Python的交互式环境中可以看到Tim Peter撰写的[“Python之禅”](../Python之禅.md),里面讲述的道理不仅仅适用于Python,也适用于其他编程语言。
|
> **说明**:输入上面的代码,在Python的交互式环境中可以看到Tim Peter撰写的[“Python之禅”](../Python之禅.md),里面讲述的道理不仅仅适用于Python,也适用于其他编程语言。
|
||||||
>
|
|
||||||
|
|
||||||
2. 学习使用turtle在屏幕上绘制图形。
|
2. 学习使用turtle在屏幕上绘制图形。
|
||||||
|
|
||||||
> 说明:turtle是Python内置的一个非常有趣的模块,特别适合对计算机程序设计进行初体验的小伙伴,它最早是Logo语言的一部分,Logo语言是Wally Feurzig和Seymour Papert在1966发明的编程语言。
|
> **说明**:turtle是Python内置的一个非常有趣的模块,特别适合对计算机程序设计进行初体验的小伙伴,它最早是Logo语言的一部分,Logo语言是Wally Feurzig和Seymour Papert在1966发明的编程语言。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
import turtle
|
import turtle
|
||||||
|
@ -260,4 +253,4 @@ PyCharm的安装、配置和使用在[《玩转PyCharm》](../玩转PyCharm.md)
|
||||||
turtle.mainloop()
|
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)科普一下。
|
计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们大多数时候使用的计算机,虽然它们的元器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](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年,IBM和Google都推出了自己的量子计算机。
|
> **说明**:近期关于**量子计算机**的研究已经被推倒了风口浪尖,量子计算机基于量子力学进行运算,使用量子瞬移的方式来传递信息。2018年6月,Intel宣布开发出新款量子芯片并通过了在接近绝对零度环境下的测试;2019年,IBM和Google都推出了自己的量子计算机。
|
||||||
|
|
||||||
### 变量和类型
|
### 变量和类型
|
||||||
|
|
||||||
在程序设计中,变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间,变量的值可以被读取和修改,这是所有计算和控制的基础。计算机能处理的数据有很多种类型,除了数值之外还可以处理文本、图形、音频、视频等各种各样的数据,那么不同的数据就需要定义不同的存储类型。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`)。
|
||||||
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
|
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
|
||||||
- 布尔型:布尔值只有`True`、`False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True`、`False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。
|
- 布尔型:布尔值只有`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
|
```Python
|
||||||
"""
|
"""
|
||||||
使用变量保存数据并进行算术运算
|
使用变量保存数据并进行加减乘除运算
|
||||||
|
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
a = 321
|
a = 321
|
||||||
b = 123
|
b = 12
|
||||||
print(a + b)
|
print(a + b) # 333
|
||||||
print(a - b)
|
print(a - b) # 309
|
||||||
print(a * b)
|
print(a * b) # 3852
|
||||||
print(a / b)
|
print(a / b) # 26.75
|
||||||
print(a // b)
|
|
||||||
print(a % b)
|
|
||||||
print(a ** b)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
在Python中可以使用`type`函数对变量的类型进行检查。程序设计中函数的概念跟数学上函数的概念是一致的,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解这个概念也不要紧,我们会在后续的章节中专门讲解函数的定义和使用。
|
在Python中可以使用`type`函数对变量的类型进行检查。程序设计中函数的概念跟数学上函数的概念是一致的,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解这个概念也不要紧,我们会在后续的章节中专门讲解函数的定义和使用。
|
||||||
|
@ -62,9 +58,7 @@ print(a ** b)
|
||||||
|
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
Date: 2018-02-27
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
a = 100
|
a = 100
|
||||||
b = 12.345
|
b = 12.345
|
||||||
c = 1 + 5j
|
c = 1 + 5j
|
||||||
|
@ -96,7 +90,6 @@ print(type(e)) # <class 'bool'>
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
a = int(input('a = '))
|
a = int(input('a = '))
|
||||||
b = int(input('b = '))
|
b = int(input('b = '))
|
||||||
print('%d + %d = %d' % (a, b, a + b))
|
print('%d + %d = %d' % (a, b, a + b))
|
||||||
|
@ -133,7 +126,9 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
|
||||||
|
|
||||||
>**说明:** 在实际开发中,如果搞不清楚运算符的优先级,可以使用括号来确保运算的执行顺序。
|
>**说明:** 在实际开发中,如果搞不清楚运算符的优先级,可以使用括号来确保运算的执行顺序。
|
||||||
|
|
||||||
下面的例子演示了赋值运算符和复合赋值运算符的使用。
|
#### 赋值运算符
|
||||||
|
|
||||||
|
赋值运算符应该是最为常见的运算符,它的作用是将右边的值赋给左边的变量。下面的例子演示了赋值运算符和复合赋值运算符的使用。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
"""
|
"""
|
||||||
|
@ -142,24 +137,26 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
a = 10
|
a = 10
|
||||||
b = 3
|
b = 3
|
||||||
a += b # 相当于:a = a + b
|
a += b # 相当于:a = a + b
|
||||||
a *= a + 2 # 相当于:a = a * (a + 2)
|
a *= a + 2 # 相当于:a = a * (a + 2)
|
||||||
print(a) # 想想这里会输出什么
|
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
|
```Python
|
||||||
"""
|
"""
|
||||||
比较、逻辑和算身份运算符的使用
|
比较运算符和逻辑运算符的使用
|
||||||
|
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
flag0 = 1 == 1
|
flag0 = 1 == 1
|
||||||
flag1 = 3 > 2
|
flag1 = 3 > 2
|
||||||
flag2 = 2 < 1
|
flag2 = 2 < 1
|
||||||
|
@ -172,10 +169,10 @@ print('flag2 =', flag2) # flag2 = False
|
||||||
print('flag3 =', flag3) # flag3 = False
|
print('flag3 =', flag3) # flag3 = False
|
||||||
print('flag4 =', flag4) # flag4 = True
|
print('flag4 =', flag4) # flag4 = True
|
||||||
print('flag5 =', flag5) # flag5 = False
|
print('flag5 =', flag5) # flag5 = False
|
||||||
print(flag1 is True) # True
|
|
||||||
print(flag2 is not False) # False
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **说明**:比较运算符的优先级高于赋值运算符,所以`flag0 = 1 == 1`先做`1 == 1`产生布尔值`True`,再将这个值赋值给变量`flag0`。`print`函数可以输出多个值,多个值之间可以用`,`进行分隔,输出的内容之间默认以空格分开。
|
||||||
|
|
||||||
### 练习
|
### 练习
|
||||||
|
|
||||||
#### 练习1:华氏温度转换为摄氏温度。
|
#### 练习1:华氏温度转换为摄氏温度。
|
||||||
|
@ -191,12 +188,17 @@ print(flag2 is not False) # False
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
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))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **说明**:在使用`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:输入圆的半径计算计算周长和面积。
|
#### 练习2:输入圆的半径计算计算周长和面积。
|
||||||
|
|
||||||
参考答案:
|
参考答案:
|
||||||
|
@ -208,12 +210,9 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c))
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
radius = float(input('请输入圆的半径: '))
|
radius = float(input('请输入圆的半径: '))
|
||||||
perimeter = 2 * math.pi * radius
|
perimeter = 2 * 3.1416 * radius
|
||||||
area = math.pi * radius * radius
|
area = 3.1416 * radius * radius
|
||||||
print('周长: %.2f' % perimeter)
|
print('周长: %.2f' % perimeter)
|
||||||
print('面积: %.2f' % area)
|
print('面积: %.2f' % area)
|
||||||
```
|
```
|
||||||
|
@ -229,11 +228,11 @@ print('面积: %.2f' % area)
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
year = int(input('请输入年份: '))
|
year = int(input('请输入年份: '))
|
||||||
# 如果代码太长写成一行不便于阅读 可以使用\对代码进行折行
|
# 如果代码太长写成一行不便于阅读 可以使用\对代码进行折行
|
||||||
is_leap = (year % 4 == 0 and year % 100 != 0) or \
|
is_leap = year % 4 == 0 and year % 100 != 0 or \
|
||||||
year % 400 == 0
|
year % 400 == 0
|
||||||
print(is_leap)
|
print(is_leap)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **说明**:比较运算符会产生布尔值,而逻辑运算符`and`和`or`会对这些布尔值进行组合,最终也是得到一个布尔值,闰年输出`True`,平年输出`False`。
|
|
@ -15,7 +15,6 @@
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
username = input('请输入用户名: ')
|
username = input('请输入用户名: ')
|
||||||
password = input('请输入口令: ')
|
password = input('请输入口令: ')
|
||||||
# 用户名是admin且密码是123456则身份验证成功否则身份验证失败
|
# 用户名是admin且密码是123456则身份验证成功否则身份验证失败
|
||||||
|
@ -25,9 +24,9 @@ else:
|
||||||
print('身份验证失败!')
|
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)
|
![$$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
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
value = float(input('请输入长度: '))
|
value = float(input('请输入长度: '))
|
||||||
unit = input('请输入单位: ')
|
unit = input('请输入单位: ')
|
||||||
if unit == 'in' or unit == '英寸':
|
if unit == 'in' or unit == '英寸':
|
||||||
|
@ -116,7 +114,6 @@ else:
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
score = float(input('请输入成绩: '))
|
score = float(input('请输入成绩: '))
|
||||||
if score >= 90:
|
if score >= 90:
|
||||||
grade = 'A'
|
grade = 'A'
|
||||||
|
@ -141,7 +138,6 @@ print('对应的等级是:', grade)
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
a = float(input('a = '))
|
a = float(input('a = '))
|
||||||
b = float(input('b = '))
|
b = float(input('b = '))
|
||||||
c = float(input('c = '))
|
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循环
|
### for-in循环
|
||||||
|
|
||||||
|
@ -24,11 +24,12 @@ for x in range(101):
|
||||||
print(sum)
|
print(sum)
|
||||||
```
|
```
|
||||||
|
|
||||||
需要说明的是上面代码中的`range(101)`可以用来构造一个从0到100的取值范围,这样就可以构造出一个整数的序列并用于循环中,例如:
|
需要说明的是上面代码中的`range(1, 101)`可以用来构造一个从1到100的范围,当我们把这样一个范围放到`for-in`循环中,就可以通过前面的循环变量`x`依次取出从1到100的整数。当然,`range`的用法非常灵活,下面给出了一个例子:
|
||||||
|
|
||||||
- `range(101)`可以产生一个0到100的整数序列。
|
- `range(101)`:可以用来产生0到100范围的整数,需要注意的是取不到101。
|
||||||
- `range(1, 100)`可以产生一个1到99的整数序列。
|
- `range(1, 101)`:可以用来产生1到100范围的整数,相当于前面是闭区间后面是开区间。
|
||||||
- `range(1, 100, 2)`可以产生一个1到99的奇数序列,其中2是步长,即数值序列的增量。
|
- `range(1, 101, 2)`:可以用来产生1到100的奇数,其中2是步长,即每次数值递增的值。
|
||||||
|
- `range(100, 0, -2)`:可以用来产生100到1的偶数,其中-2是步长,即每次数字递减的值。
|
||||||
|
|
||||||
知道了这一点,我们可以用下面的代码来实现1~100之间的偶数求和。
|
知道了这一点,我们可以用下面的代码来实现1~100之间的偶数求和。
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ for x in range(2, 101, 2):
|
||||||
print(sum)
|
print(sum)
|
||||||
```
|
```
|
||||||
|
|
||||||
也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。
|
当然,也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
"""
|
"""
|
||||||
|
@ -63,20 +64,21 @@ for x in range(1, 101):
|
||||||
print(sum)
|
print(sum)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **说明**:相较于上面直接跳过奇数的做法,下面这种做法很明显并不是很好的选择。
|
||||||
|
|
||||||
### while循环
|
### while循环
|
||||||
|
|
||||||
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环。`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`循环继续,表达式的值为`False`循环结束。下面我们通过一个“猜数字”的小游戏(计算机出一个1~100之间的随机数,人输入自己猜的数字,计算机给出对应的提示信息,直到人猜出计算机出的数字)来看看如何使用`while`循环。
|
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环。`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`则继续循环;表达式的值为`False`则结束循环。
|
||||||
|
|
||||||
|
下面我们通过一个“猜数字”的小游戏来看看如何使用`while`循环。猜数字游戏的规则是:计算机出一个1到100之间的随机数,玩家输入自己猜的数字,计算机给出对应的提示信息(大一点、小一点或猜对了),如果玩家猜中了数字,计算机提示用户一共猜了多少次,游戏结束,否则游戏继续。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
"""
|
"""
|
||||||
猜数字游戏
|
猜数字游戏
|
||||||
计算机出一个1~100之间的随机数由人来猜
|
|
||||||
计算机根据人猜的数字分别给出提示大一点/小一点/猜对了
|
|
||||||
|
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
answer = random.randint(1, 100)
|
answer = random.randint(1, 100)
|
||||||
|
@ -147,6 +149,8 @@ else:
|
||||||
|
|
||||||
#### 练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。
|
#### 练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。
|
||||||
|
|
||||||
|
> **提示**:两个数的最大公约数是两个数的公共因子中最大的那个数;两个数的最小公倍数则是能够同时被两个数整除的最小的那个数。
|
||||||
|
|
||||||
参考答案:
|
参考答案:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
Author: 骆昊
|
Author: 骆昊
|
||||||
"""
|
"""
|
||||||
|
|
||||||
m = int(input('m = '))
|
m = int(input('m = '))
|
||||||
n = int(input('n = '))
|
n = int(input('n = '))
|
||||||
fm = 1
|
fm = 1
|
||||||
|
@ -26,10 +25,10 @@ for num in range(1, m + 1):
|
||||||
fn = 1
|
fn = 1
|
||||||
for num in range(1, n + 1):
|
for num in range(1, n + 1):
|
||||||
fn *= num
|
fn *= num
|
||||||
fmn = 1
|
fm_n = 1
|
||||||
for num in range(1, m - n + 1):
|
for num in range(1, m - n + 1):
|
||||||
fmn *= num
|
fm_n *= num
|
||||||
print(fm // fn // fmn)
|
print(fm // fn // fm_n)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 函数的作用
|
### 函数的作用
|
||||||
|
@ -43,7 +42,13 @@ print(fm // fn // fmn)
|
||||||
在了解了如何定义函数后,我们可以对上面的代码进行重构,所谓重构就是在不影响代码执行结果的前提下对代码的结构进行调整,重构之后的代码如下所示。
|
在了解了如何定义函数后,我们可以对上面的代码进行重构,所谓重构就是在不影响代码执行结果的前提下对代码的结构进行调整,重构之后的代码如下所示。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
def factorial(num):
|
"""
|
||||||
|
输入M和N计算C(M,N)
|
||||||
|
|
||||||
|
Version: 0.1
|
||||||
|
Author: 骆昊
|
||||||
|
"""
|
||||||
|
def fac(num):
|
||||||
"""求阶乘"""
|
"""求阶乘"""
|
||||||
result = 1
|
result = 1
|
||||||
for n in range(1, num + 1):
|
for n in range(1, num + 1):
|
||||||
|
@ -54,10 +59,10 @@ def factorial(num):
|
||||||
m = int(input('m = '))
|
m = int(input('m = '))
|
||||||
n = int(input('n = '))
|
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
|
```Python
|
||||||
def is_prime(num):
|
def is_prime(num):
|
||||||
"""判断一个数是不是素数"""
|
"""判断一个数是不是素数"""
|
||||||
for factor in range(2, num):
|
for factor in range(2, int(num ** 0.5) + 1):
|
||||||
if num % factor == 0:
|
if num % factor == 0:
|
||||||
return False
|
return False
|
||||||
return True if num != 1 else False
|
return True if num != 1 else False
|
||||||
|
@ -286,6 +291,8 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
> **注意**:通过上面的程序可以看出,当我们**将代码中重复出现的和相对独立的功能抽取成函数**后,我们可以**组合使用这些函数**来解决更为复杂的问题,这也是我们为什么要定义和使用函数的一个非常重要的原因。
|
> **注意**:通过上面的程序可以看出,当我们**将代码中重复出现的和相对独立的功能抽取成函数**后,我们可以**组合使用这些函数**来解决更为复杂的问题,这也是我们为什么要定义和使用函数的一个非常重要的原因。
|
||||||
|
|
||||||
|
### 变量的作用域
|
||||||
|
|
||||||
最后,我们来讨论一下Python中有关变量作用域的问题。
|
最后,我们来讨论一下Python中有关变量作用域的问题。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
|
|
|
@ -652,7 +652,7 @@
|
||||||
return 1800.0 + self.sales * 0.05
|
return 1800.0 + self.sales * 0.05
|
||||||
|
|
||||||
|
|
||||||
class EmployeeFactory():
|
class EmployeeFactory:
|
||||||
"""创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)"""
|
"""创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -69,14 +69,10 @@
|
||||||
''.join(reversed('hello'))
|
''.join(reversed('hello'))
|
||||||
```
|
```
|
||||||
|
|
||||||
或
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
'hello'[::-1]
|
'hello'[::-1]
|
||||||
```
|
```
|
||||||
|
|
||||||
或
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
def reverse(content):
|
def reverse(content):
|
||||||
return ''.join(content[i] for i in range(len(content) - 1, -1, -1))
|
return ''.join(content[i] for i in range(len(content) - 1, -1, -1))
|
||||||
|
@ -84,8 +80,6 @@
|
||||||
reverse('hello')
|
reverse('hello')
|
||||||
```
|
```
|
||||||
|
|
||||||
或
|
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
def reverse(content):
|
def reverse(content):
|
||||||
return reverse(content[1:]) + content[0] if len(content) > 1 else content
|
return reverse(content[1:]) + content[0] if len(content) > 1 else content
|
||||||
|
|
|
@ -427,21 +427,21 @@ Git不像SVN那样一定需要中央服务器才能工作,上面我们演示
|
||||||
创建`feature`分支:
|
创建`feature`分支:
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
git switch -c myfeature develop
|
git switch -c feature/user develop
|
||||||
```
|
```
|
||||||
|
|
||||||
或
|
或
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
git checkout -b myfeature develop
|
git checkout -b feature/user develop
|
||||||
```
|
```
|
||||||
|
|
||||||
将`feature`分支合并到`develop`分支:
|
接下来就是在`feature`分支上进行开发并实施版本控制,这一段如何操作我们就不再赘述了。工作完成后,将`feature`分支合并到`develop`分支:
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
git checkout develop
|
git checkout develop
|
||||||
git merge --no-ff myfeature
|
git merge --no-ff feature/user
|
||||||
git branch -d myfeature
|
git branch -d feature/user
|
||||||
git push origin develop
|
git push origin develop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ tar -xvf ZenTaoPMS.pro8.5.2.zbox_64.tar
|
||||||
|
|
||||||
对敏捷开发以及敏捷闭环工具不是特别了解的,可以参考[《基于JIRA的Scrum敏捷开发的项目管理》](<https://blog.51cto.com/newthink/1775427>)一文。
|
对敏捷开发以及敏捷闭环工具不是特别了解的,可以参考[《基于JIRA的Scrum敏捷开发的项目管理》](<https://blog.51cto.com/newthink/1775427>)一文。
|
||||||
|
|
||||||
#### Gitlab
|
#### GitLab
|
||||||
|
|
||||||
常用的代码托管平台和之前提到的Git私服Gitlab都提供了缺陷管理的功能,当我们要报告一个bug时,可以在如下图所示的界面创建一个新的问题票(issue ticket)。填写的内容包括:
|
常用的代码托管平台和之前提到的Git私服Gitlab都提供了缺陷管理的功能,当我们要报告一个bug时,可以在如下图所示的界面创建一个新的问题票(issue ticket)。填写的内容包括:
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ tar -xvf ZenTaoPMS.pro8.5.2.zbox_64.tar
|
||||||
|
|
||||||
![](./res/jenkins_new_project.png)
|
![](./res/jenkins_new_project.png)
|
||||||
|
|
||||||
持续集成对于编译型语言的意义更大,对于Python这样的解释型语言,更多的时候是用于对接版本控制系统触发自动化测试并产生相应的报告,类似的功能也可以通过配置**Webhook**来完成。如果要通过Docker这样的虚拟化容器进行项目打包部署或者通过K8S进行容器管理,可以在持续集成平台安装对应的插件来支持这些功能。码云甚至可以直接对接[钉钉开放平台](<https://ding-doc.dingtalk.com/>)使用钉钉机器人来向项目相关人员发送即时消息。Gitlab也对CI和CD(持续交付)提供了支持,具体内容请大家参考[《GitLab CI/CD基础教程》](<https://blog.stdioa.com/2018/06/gitlab-cicd-fundmental/>)。
|
持续集成对于编译型语言的意义更大,对于Python这样的解释型语言,更多的时候是用于对接版本控制系统触发自动化测试并产生相应的报告,类似的功能也可以通过配置**Webhook**来完成。如果要通过Docker这样的虚拟化容器进行项目打包部署或者通过K8S进行容器管理,可以在持续集成平台安装对应的插件来支持这些功能。码云甚至可以直接对接[钉钉开放平台](<https://ding-doc.dingtalk.com/>)使用钉钉机器人来向项目相关人员发送即时消息。GitLab也对CI和CD(持续交付)提供了支持,具体内容请大家参考[《GitLab CI/CD基础教程》](<https://blog.stdioa.com/2018/06/gitlab-cicd-fundmental/>)。
|
||||||
|
|
||||||
> **说明**:
|
> **说明**:
|
||||||
>
|
>
|
||||||
|
|
|
@ -30,7 +30,7 @@ Docker属于对Linux容器技术(LXC)的一种封装(利用了Linux的name
|
||||||
uname -r
|
uname -r
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 更系统底层的库文件(建议一定要执行,否则在使用Docker时可能会出现莫名其妙的问题)。
|
2. 更新系统底层的库文件(建议一定要执行,否则在使用Docker时可能会出现莫名其妙的问题)。
|
||||||
|
|
||||||
```Bash
|
```Bash
|
||||||
yum update
|
yum update
|
||||||
|
@ -399,7 +399,7 @@ docker run -d -p 80:80 -p 22:22 --name gitlab -v /root/gitlab/config:/etc/gitlab
|
||||||
|
|
||||||
### 构建镜像
|
### 构建镜像
|
||||||
|
|
||||||
通过上面的讲解,我们已经掌握了如何通过官方提供的镜像来创建容器。当然如果愿意,我们也可以用配置好的容器来生成镜像。简而言之,Docker镜像是由文件系统叠加而成的,系统的最底层是bootfs,相当于就是Linux内核的引导文件系统;接下来第二层是rootfs,这一层可以是一种或多种操作系统(如Debian或Ubuntu文件系统),Docker中的rootfs是只读状态的;Docker利用联合挂载技术将各层文件系统叠加到一起,最终的文件系统会包含有底层的文件和目录,这样的文件系统就是一个镜像。
|
通过上面的讲解,我们已经掌握了如何通过官方提供的镜像来创建容器。当然如果愿意,我们也可以用配置好的容器来生成镜像。简而言之,**Docker镜像是由文件系统叠加而成的,系统的最底层是bootfs,相当于就是Linux内核的引导文件系统;接下来第二层是rootfs,这一层可以是一种或多种操作系统(如Debian或Ubuntu文件系统),Docker中的rootfs是只读状态的;Docker利用联合挂载技术将各层文件系统叠加到一起,最终的文件系统会包含有底层的文件和目录,这样的文件系统就是一个镜像**。
|
||||||
|
|
||||||
之前我们讲过了如何查找、列出镜像和拉取(下载)镜像,接下来看看构建镜像的两种方式:
|
之前我们讲过了如何查找、列出镜像和拉取(下载)镜像,接下来看看构建镜像的两种方式:
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,7 @@ if alipay.verify(params, params.pop('sign')):
|
||||||
1. 秒杀:秒杀是通常意味着要在很短的时间处理极高的并发,系统在短时间需要承受平时百倍以上的流量,因此秒杀架构是一个比较复杂的问题,其核心思路是流量控制和性能优化,需要从前端(通过JavaScript实现倒计时、避免重复提交和限制频繁刷新)到后台各个环节的配合。流量控制主要是限制只有少部分流量进入服务后端(毕竟最终只有少部分用户能够秒杀成功),同时在物理架构上使用缓存(一方面是因为读操作多写操作少;另外可以将库存放在Redis中,利用DECR原语实现减库存;同时也可以利用Redis来进行限流,道理跟限制频繁发送手机验证码是一样的)和消息队列(消息队列最为重要的作用就是“削峰”和“上下游节点解耦合”)来进行优化;此外还要采用无状态服务设计,这样才便于进行水平扩展(通过增加设备来为系统扩容)。
|
1. 秒杀:秒杀是通常意味着要在很短的时间处理极高的并发,系统在短时间需要承受平时百倍以上的流量,因此秒杀架构是一个比较复杂的问题,其核心思路是流量控制和性能优化,需要从前端(通过JavaScript实现倒计时、避免重复提交和限制频繁刷新)到后台各个环节的配合。流量控制主要是限制只有少部分流量进入服务后端(毕竟最终只有少部分用户能够秒杀成功),同时在物理架构上使用缓存(一方面是因为读操作多写操作少;另外可以将库存放在Redis中,利用DECR原语实现减库存;同时也可以利用Redis来进行限流,道理跟限制频繁发送手机验证码是一样的)和消息队列(消息队列最为重要的作用就是“削峰”和“上下游节点解耦合”)来进行优化;此外还要采用无状态服务设计,这样才便于进行水平扩展(通过增加设备来为系统扩容)。
|
||||||
2. 超卖现象:比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商品的库存被修改为0,而此时用户2并不知道的情况下提交订单,该商品的库存再次被修改为-1这就是超卖现象。解决超卖现象有三种常见的思路:
|
2. 超卖现象:比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商品的库存被修改为0,而此时用户2并不知道的情况下提交订单,该商品的库存再次被修改为-1这就是超卖现象。解决超卖现象有三种常见的思路:
|
||||||
- 悲观锁控制:查询商品数量的时候就用`select ... for update`对数据加锁,这样的话用户1查询库存时,用户2因无法读取库存数量被阻塞,直到用户1提交或者回滚了更新库存的操作后才能继续,从而解决了超卖问题。但是这种做法对并发访问量很高的商品来说性能太过糟糕,实际开发中可以在库存小于某个值时才考虑加锁,但是总的来说这种做法不太可取。
|
- 悲观锁控制:查询商品数量的时候就用`select ... for update`对数据加锁,这样的话用户1查询库存时,用户2因无法读取库存数量被阻塞,直到用户1提交或者回滚了更新库存的操作后才能继续,从而解决了超卖问题。但是这种做法对并发访问量很高的商品来说性能太过糟糕,实际开发中可以在库存小于某个值时才考虑加锁,但是总的来说这种做法不太可取。
|
||||||
- 乐观锁控制:查询商品数量不用加锁,更新库存的时候设定商品数量必须与之前查询数量相同才能更新,否则说明其他事务已经更新了库存,必须重新发出请求。这种做法要求事务隔离级别为可重复读(repeatable read),否则仍然会产生问题。
|
- 乐观锁控制:查询商品数量不用加锁,更新库存的时候设定商品数量必须与之前查询数量相同才能更新,否则说明其他事务已经更新了库存,必须重新发出请求。
|
||||||
- 尝试减库存:将上面的查询(`select`)和更新(`update`)操作合并为一条SQL操作,更新库存的时候,在`where`筛选条件中加上`库存>=购买数量`或`库存-购买数量>=0`的条件,这种做法要求事务隔离级别为读提交(read committed)。
|
- 尝试减库存:将上面的查询(`select`)和更新(`update`)操作合并为一条SQL操作,更新库存的时候,在`where`筛选条件中加上`库存>=购买数量`或`库存-购买数量>=0`的条件,这种做法要求事务隔离级别为读提交(read committed)。
|
||||||
|
|
||||||
> 提示:有兴趣的可以自己在知乎上看看关于这类问题的讨论。
|
> 提示:有兴趣的可以自己在知乎上看看关于这类问题的讨论。
|
||||||
|
|
|
@ -292,7 +292,7 @@ pip install -r code/teamproject/requirements.txt
|
||||||
|
|
||||||
```Nginx
|
```Nginx
|
||||||
# 配置用户
|
# 配置用户
|
||||||
user root;
|
user nginx;
|
||||||
# 工作进程数(建议跟CPU的核数量一致)
|
# 工作进程数(建议跟CPU的核数量一致)
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
# 错误日志
|
# 错误日志
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
## Python - 100天从新手到大师
|
## Python - 100天从新手到大师
|
||||||
|
|
||||||
> 作者:骆昊
|
> **作者**:骆昊
|
||||||
>
|
>
|
||||||
> 最近有很多想学习Python的小伙伴陆陆续续加入我们的交流群,目前我们的交流群人数已经超过一万人。我们的目标是打造一个优质的Python交流社区,一方面为Python初学者扫平入门过程中的重重障碍,另一方为新入行的开发者提供问道的门径,帮助他们迅速成长。我自己很希望更多有经验的开发者加入到这个平台,把自己的工作经验无偿分享或有偿提供出来,让大家最终都能够通过这个平台获取对自己有帮助的信息。我的知乎号是[Python-Jack](https://www.zhihu.com/people/jackfrued),之前是我的团队在协助运营,从现在开始我会自己管理这个知乎号,持续为大家提供高质量的文章和新的学习内容,也欢迎大家关注我在知乎的文章和问题回答。创作不易,感谢大家的打赏支持,这些钱不会用于购买咖啡而是通过腾讯公益平台捐赠给需要帮助的人([点击](./更新日志.md)了解捐赠情况)。
|
> **说明**:从项目上线到获得8w+星标以来,一直收到反馈说基础部分(前15天的内容)对新手来说是比较困难的,建议有配套视频进行讲解。最近把基础部分的内容重新创建了一个名为[“Python-Core-50-Courses”](<https://github.com/jackfrued/Python-Core-50-Courses>)的项目,**用更为简单通俗的方式重写了这部分内容并附带了视频讲解**,初学者可以关注下这个新项目。国内用户如果访问GitHub比较慢的话,也可以关注我的知乎号[Python-Jack](https://www.zhihu.com/people/jackfrued)上的[“从零开始学Python”](<https://zhuanlan.zhihu.com/c_1216656665569013760>)专栏,专栏会持续更新,还有大家比较期待的“数据分析”的内容也即将上线,**欢迎大家关注我在知乎的专栏、文章和回答**。
|
||||||
|
>
|
||||||
|
> 创作不易,感谢大家的打赏支持,这些钱基本不会用于购买咖啡,而是通过腾讯公益、美团公益、水滴筹等平台捐赠给需要帮助的人([点击](./更新日志.md)了解捐赠情况)。需要加入QQ交流群的可以扫描下面的二维码,交流群会为大家提供**学习资源**和**问题解答**,还会持续为大家带来**免费的线上Python体验课和行业公开课**,敬请关注。
|
||||||
|
|
||||||
![](./res/python-qq-group.png)
|
![](./res/python-qq-group.png)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue