精通Python自动化脚本-第一章 Python脚本概述
精通Python自动化脚本-运维人员宝典完整目录:
第一章 Python脚本概述
第二章 Python脚本调试和性能测试
第三章 单元测试-单元测试框架的介绍
第四章 自动化常规运维活动
第五章 文件、目录和数据处理
第六章 文件存档、加密和解密
第七章 文本处理和正则表达式
第八章 文档和报告
第九章 操作各类文件
第十章 网络基础 - Socket编程
第十一章 使用Python脚本处理邮件
第十二章 使用Telnet和SSH远程监控主机
第十三章 创建图形化用户界面
第十四章 处理Apache和其它的日志文件
第十五章 SOAP和REST API通讯
第十六章 网络抓取 - 从网站上提取有用的信息
第十七章 数据收集及报表
第十八章 MySQL和SQLite数据库管理
技术要求
在学习本书前,你应该了解一些 Python 编程的基础知识,比如基础语法、变量类型、元组数据类型、列表字典、函数、字符串和方法。在python.org/downloads/上有3.7.2和2.7.15两个版本可供下载。本书中我们将使用3.7这一版本来作为代表示例和包的安装。
译者注:预计 Python 3.7还会发展较长时间,而 Python2则长期止步于 Python2.7了,但小版本号都在不断变化
本章的示例和源代码可通过 GitHub 仓库进行获取。
为什么选择Python?
Python有非常丰富的开源库用于数据分析工具、网站框架、测试等等。Python是一种可在不同平台上使用的编程语言(Windows, Mac, Linux和Linux嵌入式硬件,如树莓派Raspberry Pi)。它也用于开发桌面应用和网页应用。
开发人员如果使用Python可以编写更少行数的代码。原型制作非常快速,因为在解释器系统中运行。Python可被看成是面向对象、面向过程或函数式编程。
Python可以完成各种任务,比如创建网页应用。它和软件一起使用来创建工作流,它连接数据库系统、处理文件、处理大数据并执行复杂数学运算。
Python语法与其它编程语言的对比
Python编写的代码可读性很强,因为它和英语本身非常相近。要完成一个命令,Python使用新的一行来完成。
Python有一个很棒的特性:缩进。使用缩进我们可以定义决策语句作用域,for循环和while循环、函数和类。
Python安装
这一部分中我们将学习在不同平台上Python的安装,比如Linux和Windows。
Linux平台上的安装
大部分Linux发行版本都默认安装了Python 2。有些则直接包含了Python 3。
译者注:目前大部分 CentOS 中默认安装的是 Python 2,而 Ubuntu 中则内置了 Python 3
要在Debian系Linux系统中安装Python 3,在命令行终端中可运行如下命令:
sudo apt install python3
要在CentOS 系统中安装Python 3,在命令行终端中可运行如下命令:
sudo yum install python3
如无法使用以上命令安装Python,请从官方网站上下载Python并按照指示进行安装。
译者注:本博客有一篇如何安装Python3.7也可供参考
Windows平台上的安装
在Microsoft Windows上安装Python,我们需要从python.org上下载可执行安装包并执行安装。从官网下载页面下载python.exe文件并选择想要在电脑了安装的Python版本。然后双击所下载的 exe 文件来安装Python。有安装引导页面中,有一个Add Python to the path的复选框,勾选并按照提示一步一步的安装Python 3。
Pip安装以及使用pip安装Python包
在 Linux 中安装pip命令如下:
sudo apt install python-pip # 安装 Python 2的 pip
sudo apt install python3-pip # 安装 Python 3的 pip
译者注:以上为 Ubuntu 中的命令,原书作者使用的均为 Ubuntu,CentOS 中将 apt 修改为 yum 即可
Windows中, 使用如下命令安装:
python -m pip install pip
Mac上的安装
要安装 Python 3,我们要在系统中安装brew。运行如下命令来在系统中安装brew:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
通过运行以上命令,brew就安装好了。现在使用brew来安装 Python 3:
brew install python3
安装Jupyter notebook
要安装Jupyter Notebook,先下载Anaconda。
安装所下载的Anaconda版本,按照向导中的指示进行安装即可。
使用pip安装Jupyter:
pip install jupyter
在 Linux 中,pip install jupyter安装的是Python 2 的Jupyter。如果想要安装Python 3 的Jupyter,运行如下命令:
pip3 install jupyter
安装和使用虚拟环境
下面我们就来看如何安装虚拟环境以及如何进行激活。
在Linux中安装虚拟环境,执行步骤如下:
1、首先检查是否安装了pip。我们来安装Python 3的pip
sudo apt install python3-pip
2、使用pip3安装虚拟环境:
sudo pip3 install virtualenv
3、现在我们来创建虚拟环境。你可以选择任意名称,这里我们使用pythonenv:
virtualenv pythonenv
4、激活虚拟环境:
source pythonenv/bin/activate
5、在完成操作之后,还可通过以下命令来关闭virtualenv:
deactivate
在Windows中, 运行pip install virtualenv命令来安装虚拟环境。virtualenv的安装步骤与Linux相同。
译者注:在安装了virtualenv之后,还可安装 Virtualenv Wrapper来更方便管理虚拟环境,关于环境搭建还可参见本博客Django环境搭建及开发
安装Installing Geany和PyCharm
通过https://www.geany.org/download/releases下载Geany并下载所需的二进行文件。根据指示来进行安装。
通过https://www.jetbrains.com/pycharm/download/下载PyCharm并根据指示来进行安装。
Python 解释器
Python是一种解释性语言。有一个称为Python解释器或Python shell的交互式终端。这个shell可供我们无需创建脚本来逐行执行程序。
我们可以在这个Python交互式终端中访问Python的内置函数和库、安装模块和命令执行历史。这个终端为我们提供了研究Python的机会。你可以将准备好的代码拷贝到脚本中。
Python和Bash脚本的区别
这一部分中,我们将学习Python和Bash脚本的区别。它们的区别如下:
- Python是一种脚本语言,而Bash是一种用于进入和执行命令的shell
- 使用Python更易于处理更大的程序
- Python中大部的事通过导入模块来使用一行代码调用函数
开启交互终端
我们可以在已安装了Python的电脑上访问Python交互终端。运行如下命令来开启Python交互终端:
$ python
译者注:在 Linux 中#号提示符为 root 用户,其它用户为$
以上命令将启动默认的Python交互终端。
Linux中如查在终端中写入 python,开启的是python2.7的终端。如果你想要启动python3的终端,则在终端中输入python3并按下 Enter 键。
在Windows中,我们可以在Command命令行中输入 python,就会在终端中启动所下载的Python版本。
使用Python交互终端编写脚本
Python交互终端的起始提示符为>>>。在该终端中可输入Python命令,在>>>之后进行编写。如以下截图所示:
Python 3命令行现在,我们来看如何为变量赋值,示例如下:
>>> name = 'John'
这时我们为name变量赋了一个字符串值John。按下Enter进入了一个以>>>提示符开头的新行:
>>> name = 'John'
>>>
现在,我们来看一个为变量赋值的示例并执行数学运算来获取值:
>>> num1 = 5000
>>> num2 = 3500
>>> num3 = num1 + num2
>>> print(num3)
8500
>>> num4 = num3 - 2575
>>> print(num4)
5925
>>>
这里我们对不同的变量进行赋值,对两个变量进行相加,并将和存储在了第三个变量中,还在终端(Terminal)中打印出了和。然后,我们对结果变量进行了求减运算,将输入存到了第四个变量中。接着我们将差在终端中进行了打印。这告诉我们可以使用 Python 解释器作为计算器来进行使用。
>>> 509 / 22
23.136363636363637
>>>
以上,我们执行了除法运算。509除以22并得到了商23.136363636363637。
多行模式
在Python解释器中编写多行代码时(比如 if 语句、 for循环、while 循环和函数),解释器会使用三个点(...) 作为二级提示符来延续代码行。要退出这些行,我们需要连续按下两次 Enter 键。我们来看看如下的示例:
>>> val1 = 2500
>>> val2 = 2400
>>> if val1 > val2:
... print("val1大于val2")
... else:
... print("val2大于val1")
...
val1大于val2
>>>
本例中,我们对两个变量val1和val2进行了整数值的赋值,并检查val1是否大于val2。上例中val1大于val2,因此 if 代码块中的语句执行了打印。注意 if 和 else 代码块中的语句需要进行缩进。如果不使用缩进,就会得到如下报错:
>>> if val1 > val2:
... print("val1大于val2")
File "<stdin>", line 2
print("val1大于val2")
^
IndentationError: expected an indented block
通过Python解释器导入模块
如果你导入任何模块,Python解释器会检查该模块是否存在。我们可通过 import 语句来进行实现。如果该模块存在,在按下 Enter 键之后就可以看到>>> 前置提示符。这表示执行成功。如果该模块不存在,则会在Python解释器中显示报错。
>>> import time
>>>
在导入time模块之后,我们获得了>>> 前置提示符,这表示该模块存在并且这条命令成功执行了:
<pre class="lang:default decode:true">>>> import matplotlib</pre>
如果模块不存在,就会返回Traceback的报错:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'matplotlib'
这里matplotlib不可用,因此给出了报错:ImportError: No module named 'matplotlib'。
要解决这一报错,我们需要安装matplotlib(译者注:pip3 install matplotlib)然后再次导入matplotlib。在安装matplotlib之后,就能够导入这一模块了,如下:
>>> import matplotlib
>>>
退出Python终端
在Python终端有两种方式可以退出:
- 快捷键: Ctrl + D
- 使用quit()或exit()函数
快捷键
使用快捷键Ctrl + D将会得到如下代码:
>>> val1 = 5000
>>> val2 = 2500
>>>
>>> val3 = val1 - val2
>>> print (val3)
2500
>>>
vagrant@ubuntu-xenial:~$
使用quit()或exit() 函数
使用quit()可退出Python交互终端,会回到原来的命令终端:
>>> Lion = 'Simba'
>>> quit()
vagrant@ubuntu-xenial:~$
缩进和制表符Tab
在Python中编写代码块必须使用缩进。缩进有助于编写函数、决策语句、循环语句和类。这让Python程序的读取更为容易。
我们使用缩进来表示Python程序的代码块。对代码块的缩进,可以使用空格或制表符(tab)。参见如下示例:
if val1 > val2:
print ("val1大于val2")
print("这部分代码没有进行缩进")
在上例中,我们对print语句进行了缩进,因为它位于 if 代码块中。第二个print语句不在 if 代码块中,所以没有对其进行缩进。
变量
类似一些其它编程语言,Python 中无需事先声明变量。Python 中可以想一个任意名称来作为变量名并进行赋值(译者注:仅能使用字母、数字和下划线且不能以数学开头)。可以在我们的程序中使用该变量。因此,Python 中我们可以在任何需使用的时候声明变量。
Python 中变量的值以及类型都可以在程序的执行过程中进行修改。以下代码中我们对变量赋值100:
>>> n = 100 # 这里我们对变量 n 赋值100,并在下面对n 的值加1
>>> n = n + 1
>>> print(n)
101
>>>
以下为在执行过程中变量类型可进行改变的示例:
>>> a = 50 # 数据类型被隐式地设置为整型
>>> a = 50 + 9.50 # 数据类型被修改为浮点型
>>> a = "Seventy" # 现在变成了字符串类型
Python处理不同数据类型的展现,也即不同类型的值会存储在不同的内存空间中。变量是我们用于赋值的名称:
>>> msg = 'And now for something completely different'
>>> a = 20
>>> pi = 3.1415926535897932
上例中进行了三次赋值。第一次将一个字符串赋值为名为msg的变量。第二次将一个整型赋值为名为a的变量,最后一次是一个圆周率pi值的赋值。
变量的类型为它所引用的值的类型,查看以下代码:
>>> type(msg)
<class 'str'>
>>> type(a)
<class 'int'>
>>> type(pi)
<class 'float'>
创建变量和赋值
在Python中,变量无需显式的进行声明来保留内存空间。在对变量进行赋值即会自动完成声明。Python中单个等号=用于为变量赋值。
思考如下示例的执行:
#!/usr/bin/python3
name = 'John'
age = 25
address = 'USA'
percentage = 85.5
print(name)
print(age)
print(address)
print(percentage)
输出如下:
John
25
USA
85.5
在上例中,我们将John赋值给变量name、25赋值给变量age、USA赋值给变量address以及将85.5赋值给变量percentage。
我们无需像在其它编程语言中那样事先声明变量。因此,查看值的解释器可获得变量的类型。在前例中,name和address是字符串类型,age是整型,percentage是浮点类型。
使用同一值进行多个变量的赋值可以这样做:
x = y = z = 1
上例中我们创建了三个变量并使用整数1为它们赋值,会为这三个变量分配同一个内存地址。
在Python中,我们还可以在同一行中对多个变量赋多个值:
x, y, z = 10, 'John', 80
这里我们声明一个字符串变量y,将John赋值给它,以及两个整型变量x和z,分别用10和80为它们赋值。
数值
Python解释器也可发挥计算器的作用。只需输入表达式,它就会返回值。括号( )用于进行分组,如下例如所示:
>>> 5 + 5
10
>>> 100 - 5*5
75
>>> (100 - 5*5) / 15
5.0
>>> 8 / 5
1.6
整型数值是int类型,小数部分是float类型。
ℹ️在Python中,除法(/) 运算符总是返回浮点值。向下取整运算符(//)获取的是整型结果。%运算符用于计算余数。
思考如下示例:
>>> 14/3
4.666666666666667
>>> 14//3
4
>>> 14%3
2
>>> 4*3+2
14
计算幂值(指数运算),Python使用**运算符,如下例所示:
>>> 8**3
512
>>> 5**7
78125
等号(=)用于对变量赋值:
>>> m = 50
>>> n = 8 * 8
>>> m * n
3200
如果变量不存在,而我们还是使用该变量,那么解释器会显示错误:
>>> k
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'k' is not defined
>>>
如果运算符连接不同类型的操作数,那么得到的值将会是浮点数:
>>> 5 * 4.75 - 1
22.75
在Python交互终端中,_包含上一次打印过的表达式值,如下例所示:
>>> a = 18.5 / 100
>>> b = 150.50
>>> a * b
27.8425
>>> b + _
178.3425
>>> round(_, 2)
178.34
数值数据类型存储数字,这是一种不可变的数据类型。如果进行改变,Python会为修改的数据类型分别一个新的对象。
我们可以通过赋值来创建数值对象,示例如下:
>>> num1 = 50
>>> num2 = 25
del语句用于删除单个或多个变量。参考如下示例:
>>> num = num_a = num_b = 1
>>> del num
>>> del num_a, num_b
数值类型转换
在一些情况下,我们需要显式地将数字从一个类型转换为另一种类型来满足一些要求。Python在一个表达式中内部实现。
- 输入int(a)来将a转换为整型
- 输入float(a)来将a转换为浮点数
- 输入complex(a)来将a转换复数,实部为a,虚部为0
- 输入complex(a, b)来将a和 b转换为实部为a,虚部为b 的复数。a和 b为数字表达式
字符串
和数值类型,字符串也是Python中一种数据结构。Python可以操作字符串。字符串可通过如下方式表示:
- 包含在单引号('...')中
- 包含在双引号("...")中
参见如下示例:
>>> 'Hello Python'
'Hello Python'
>>> "Hello Python"
'Hello Python'
字符串是一组字符。我们可以像下面这样一次访问一个字符:
>>> city = 'delhi'
>>> letter = city[1]
>>> letter = city[-3]
在第二个语句中,我们从city中选择数字为1的字符并将其赋值给letter。方括号中的数字为索引。索引表示要访问的字符,它从0开始。因此在前例中执行在赋值后输入 letter,将得到如下输出:
city d e l h i
索引 0 1 2 3 4
-5 -4 -3 -2 -1
输出:
e
l
字符串拼接(+)和重复(*)
下一步我们来进行字符串的拼接和重复。参照如下代码:
>>> 3 * 'hi' + 'hello'
'hihihihello'
上例中,我们进行字符串拼接和重复。3 * 'hi'表示打印hi三次,使用+符号,我们在hi之后连接了字符串hello。
我们可以通过把字符串连续放在一起自动拼接两个字符串。这两个字符串必须包含在引号之间,如下所示:
>>> 'he' 'llo'
'hello'
这一特性在字符串很长又想要分开输入时非常有用,示例如下:
>>> str = ('Several strings'
... ' joining them together.')
>>> str
'Several strings joining them together.'
字符串切片
字符串支持切片(slice)操作,这表示从字符串获取指定范围的字符。我来看看下面的例子。注意起始的索引值是包含在内的,而结束值则排除在外。
假设字符串为str = "Programming":
>>> str[0:2]
'Pr'
>>> str[2:5]
'ogr'
默认省略不写的第一个索引为0(省略第二个索引默认获取第一个索引到最后的所有字符),如下例所示:
>>> str = "Python"
>>> str[:2] + str[2:]
'Python'
>>> str[:4] + str[4:]
'Python'
>>> str[:2]
'Py'
>>> str[4:]
'on'
>>> str[-2:]
'on'
访问字符串中的值
我们可以通过方括号使用切片来访问字符串中的字符。我们还可以访问字符串中指定范围内的字符。参照如下示例:
#!/usr/bin/python3
str1 = 'Hello Python!'
str2 = "Object Oriented Programming"
print("str1[0]: ", str1[0])
print("str2[1:5]: ", str2[1:5])
输出:
str1[0]: H
str2[1:5]: bjec
更新字符串
我们可以对一个指定索引重新赋新值来更新字符串。参照如下示例:
#!/usr/bin/python3
str1 = 'Hello Python!'
print("Updated String: - ", str1[:6] + 'John')
输出:
Updated String: - Hello John
转义字符
Python 支持不可打印的转义字符(escape character),可通反斜线标记来进行展示。转义字符在单引号和双引号字符串中均可进行解释:
| 标记 | 十六进制字符 | 描述 |
| a | 0x07 | 响铃或警告 |
| b | 0x08 | 退格(Backspace) |
| cx | | Control-x |
| n | 0x0a | 新起一行 |
| C-x | | Control-x |
| e | 0x1b | 转义 |
| f | 0x0c | 换页 |
| s | 0x20 | 空格 |
| M-C-x | | Meta-control-x |
| x | | 字符x |
| nnn | | 八进行标记,n为0到7范围内的值 |
| r | 0x0d | 回车 |
| xnn | | 十六进制标记,n为0-9, a-f或A-F范围内的值 |
| t | 0x09 | Tab制表符 |
| v | 0x0b | 垂直制表符 |
特殊的字符串运算符
下表中显示了字符串的特殊运算符,假定a为Hello,b为World:
| 运算符 | 描述 | 示例 |
| + | 拼接:将运算符两边的值相加 | a + b将得到HelloWorld |
| [] | 切片:得到给定索引的字符串 | a[7]将得到r |
| [ : ] | 范围切片:得到指定范围内的字符 | a[1:4]将得到ell |
| * | 重复:创建新的字符串,将相同字符串的多个拷贝进行拼接 | a*2将得到HelloHello |
| not in | 成员:如果字符不在字符串中返回true | Z not in a将得到1 |
| in | 成员:如果字符在字符串中返回true | H in a将得到1 |
| % | 格式化:执行字符串格式化 | |
%字符串格式化运算符
%是Python中的一个字符串格式化运算符。参照如下示例:
#!/usr/bin/python3
print("Hello this is %s and my age is %d !" % ('John', 25))
输出:
Hello this is John and my age is 25 !
下表显示了配合%使用的符号列表:
| 序号 | Format symbol and conversion |
| 1 | %c – 字符 |
| 2 | %s – 在格式化之前通过str()转换的字符串 |
| 3 | %i – 有符号十进制整数 |
| 4 | %d – 有符号十进制整数 |
| 5 | %u – 无符号十进制整数 |
| 6 | %o – 八进制整数 |
| 7 | %x – 十六进制整数(小写字母) |
| 8 | %X –十六进制整数(大写字母) |
| 9 | %e – 指数标记(使用小写 e) |
| 10 | %E –指数标记(使用大写 E) |
| 11 | %f – 浮点实数 |
Python中的三引号
Python对字符串使用三引号的表示可跨越多行,包括新行和制表符。三引号的语法包含三个连续的单引号或双引号。参照如下代码:
#!/usr/bin/python3
para_str = """Python is a scripting language which was created by
Guido van Rossum in 1991, t which is used in various sectors such as Game
Development, GIS Programming, Software Development, web development,
Data Analytics and Machine learning, System Scripting etc.
"""
print (para_str)
输出内容:
Python is a scripting language which was created by
Guido van Rossum in 1991, t which is used in various sectors such as Game
Development, GIS Programming, Software Development, web development,
Data Analytics and Machine learning, System Scripting etc.<
字符串是不可变的
字符串是不可变的,表示我们修改它的值。参照如下示例:
>>> welcome = 'Hello, John!'
>>> welcome[0] = 'Y'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
因为字符串是不可变的(immutable),我们不能修改现有字符串。但我们可以创建一个与原来不同的新字符串:
>>> str1 = 'Hello John'
>>> new_str = 'Welcome' + str1[5:]
>>> print(str1)
Hello John
>>> print(new_str)
Welcome John
>>>
理解列表
Python支持一种称为列表(list)的数据结构,它是一个可变和有序的元素序列。列表中的每个元素称为列表项。列表通过在方括号[ ]之间插入值定义。列中的每个元素都会给定一个数值,称们称之为位置或索引。索引从0开始,也即,第一个索引为0,第二个索引为1,以此类推。我们可对列表进行如下运算:索引、切片、相加、相乘以及检查是否为列表成员。
Python内置的length函数返回列表的长度。Python还有查找列表中最大项和最小项的函数。列表可以是数值列表、字符串列表或混合列表。
以下是创建列表的代码:
>>> l = list()
>>> numbers = [10, 20, 30, 40]
>>> animals = ['Dog', 'Tiger', 'Lion']
>>> list1 = ['John', 5.5, 500, [100, 450]]
这里我们创建了三个列表:第一个是numbers,第二是animals,第三个是list1。列表中有另一个列表称为嵌套列表。list1是一个嵌套列表。不包含任何元素的列表称为空列表,可通过空的中括号[]来创建空列表。
你可能已经猜,可将列表赋值给变量:
>>> cities = ['Mumbai', 'Pune', 'Chennai']
>>> numbers_list = [75, 857]
>>> empty_list = []
>>> print(cities, numbers_list, empty_list)
['Mumbai', 'Pune', 'Chennai'] [75, 857] []
访问列表中的值
我们可以使用索引值来访问列表中的值。我们将索引数字放在[ 和 ]之间。索引从0开始。参见如下示例:
#!/usr/bin/python3
cities = ['Mumbai', 'Bangalore', 'Chennai', 'Pune']
numbers = [1, 2, 3, 4, 5, 6, 7]
print(cities[0])
print(numbers[1:5])
输出结果:
Mumbai
[2, 3, 4, 5]
更新列表
可以更新列表中的元素,如以下代码所示:
#!/usr/bin/python3
cities = ['Mumbai', 'Bangalore', 'Chennai', 'Pune']
print('Original Value: ', cities[3])
cities[3] = 'Delhi'
print('New value: ', cities[3])
输出结果:
Original Value: Pune
New value: Delhi
删除列表元素
要删除列表中元素,如果知道要具体删除的元素可使用del语句。如果不知道具体要删除的列表项索引可使用remove()。参见如下示例:
#/usr/bin/python3
cities = ['Mumbai', 'Bangalore', 'Chennai', 'Pune']
print("Before deleting: ", cities)
del cities[2]
# cities.remove("Chennai") # 相同效果的补充
print("After deleting: ", cities)
输出结果:
Before deleting: ['Mumbai', 'Bangalore', 'Chennai', 'Pune']
After deleting: ['Mumbai', 'Bangalore', 'Pune']
基本列表运算
有五种基本列表运算:
- 拼接
- 重复
- 取长度
- 成员关系
- 迭代
| 描述 | 表达式 | 结果 |
| 拼接 | [30, 50, 60] + ['Hello', 75, 66] | [30, 50, 60, 'Hello', 75, 66] |
| 成员 | 45 in [45, 58, 99, 65] | True |
| 迭代 | for x in [45, 58, 99]:
print(x, end=' ') | 45 58 99 |
| 重复 | ['Python'] * 3 | ['Python', 'Python', 'Python'] |
| 取长度 | len([45, 58, 99, 65]) | 4 |
列表运算
在这一部分中,我们将学习基本列表运算:拼接和重复。
+运算符将列表进行拼接:
>>> a = [30, 50, 60]
>>> b = ['Hello', 75, 66]
>>> c = a + b
>>> print(c)
[30, 50, 60, 'Hello', 75, 66]
相似地,*运算符以给定次数重复列表:
>>> [0] * 4
[0, 0, 0, 0]
>>> ['Python'] * 3
['Python', 'Python', 'Python']
索引、切片和矩阵
列表索引与字符串索引的运作方式相同。列表值可通过索引来访问。如果尝试将不存在的元素写入列表,会得到IndexError。如果索引为负值,会从列表的最后开始倒数。
现在我们创建一个名为cities的列表并查看列表的索引运算:
cities = ['Mumbai', 'Bangalore', 'Chennai', 'Pune']
| 描述 | 表达式 | 结果 |
| 索引从0开始 | cities[2] | 'Chennai' |
| 切片:获取一个片段 | cities[1:] | ['Bangalore', 'Chennai', 'Pune'] |
| 负数:从右开始数 | cities[-3] | 'Bangalore' |
元组
Python 的元组(tuple)数据结构是不可变的,这表示不能修改元组中的元素。 基本上,元组是一个以逗号分隔的值的序列,以括号( )进行包裹。和列表类似,元组是一个有序的元素序列:
t1 = 'h', 'e', 'l', 'l', 'o'
元组以括号( )进行包裹:
t1 = ('h', 'e', 'l', 'l', 'o')
我们还可以创建一个只有一个元素的元组,仅需在元组的最后加一个逗号:
>>> t1 = 'h',
>>> type(t1)
<class 'tuple'>
把值放到括号中并不是元组:
>>> t1 = ('a')
>>> type(t1)
<class 'str'>
我们可以使用tuple()函数来创建空的元组:
>>> t1 = tuple()
>>> print(t1)
()
如果该函数的参数是一个序列(字符串、列表或元组),结果是这个序列元素组成的元组:
<pre class="lang:default decode:true ">>>> t = tuple('mumbai')
print(t)
('m', 'u', 'm', 'b', 'a', 'i')</pre>
元组的值在括号( ) 中以逗号分隔:
>>> t = ('a', 'b', 'c', 'd', 'e')
>>> print(t[0])
a
切片运算符选取一个范围内的元素。
>>> print(t[1:3])
('b', 'c')
访问元组中的值
要访问元组中的值,使用方括号切片与单个或多个索引结合来获取对应索引的值,如下例所示:
#!/usr/bin/python3
cities = ('Mumbai', 'Bangalore', 'Chennai', 'Pune')
numbers = (1, 2, 3, 4, 5, 6, 7)
print(cities[3])
print(numbers[1:6])
输出结果:
Pune
(2, 3, 4, 5, 6)
更新元组
在Python中元组是不可更新的,因为元组是不可变的。但是我们通过现在元组来新建一个元组,如下例如下:
#!/usr/bin/python3
cities = ('Mumbai', 'Bangalore', 'Chennai', 'Pune')
numbers = (1, 2, 3, 4, 5, 6, 7)
tuple1 = cities + numbers
print(tuple1)
输出结果:
('Mumbai', 'Bangalore', 'Chennai', 'Pune', 1, 2, 3, 4, 5, 6, 7)
删除元组元素
我们不能删除单个数据元组。因此要显式地删除整个元组,使用del语句。参照如下示例:
#!/usr/bin/python3
cities = ('Mumbai', 'Bangalore', 'Chennai', 'Pune')
print("Before deleting: ", cities)
del cities
print("After deleting: ", cities)
输出结果:
Before deleting: ('Mumbai', 'Bangalore', 'Chennai', 'Pune')
Traceback (most recent call last):
File "test.py", line 5, in <module>
print("After deleting: ", cities)
NameError: name 'cities' is not defined
基本元组运算
和列表相似,有五种基本元组运算:
- 拼接
- 重复
- 取长度
- 成员关系
- 迭代
| 描述 | 表达式 | 结果 |
| 拼接 | (30, 50, 60) + ('Hello', 75, 66) | (30,50,60,'Hello',75,66) |
| 成员 | 45 in (45, 58, 99, 65) | True |
| 迭代 | for x in (45, 58, 99):
print(x, end=' ') | 45 58 99 |
| 重复 | ('Python') * 3 | ('Python', 'Python', 'Python') |
| 取长度 | len((45, 58, 99, 65)) | 4 |
索引、切片和矩阵
元组索引的运作方式和列表相同。使用索引可访问元组的值。如果尝试读取或写入不存在的元素,会报出IndexError。如果索引为负值,则从元组的最后向前数。
现在我们创建一个名为cities的元组并查看列表的索引运算:
cities = ('Mumbai', 'Bangalore', 'Chennai', 'Pune')
| 描述 | 表达式 | 结果 |
| 索引从0开始 | cities[2] | 'Chennai' |
| 切片:获取一个片段 | cities[1:] | ('Bangalore', 'Chennai', 'Pune') |
| 负数:从右开始数 | cities[-3] | 'Bangalore' |
max()和min()
使用max()和min()函数,我们可以查找元组中的最大值和最小值。这两个函数让我们可以找到量化数据的相关信息。我们来看看下面这个例子:
>>>> numbers = (50, 80, 98, 110.5, 75, 150.58)
>>> print(max(numbers))
150.58
使用max()可以获取元组中的最大值。相似地,我们可以使用min()函数:
>>> numbers = (50, 80, 98, 110.5, 75, 150.58)
>>> print(min(numbers))
50
因此这里我们获取到了最小值。
集合
集合(set)是一个无序且无重复值的元素集。集合的基本用法是检查成员关系测试和删除重复项。这些集合对象支持数学运算,如并集、交集、差集以及对等差分。我们可以使用大括号{}或函数set()来创建集合。如果想要创建一个空的集合,使用set()而不是{}。
以下是一个简单的演示:
>>> fruits = {'Mango', 'Apple', 'Mango', 'Watermelon', 'Apple', 'Orange'}
>>> print(fruits)
{'Orange', 'Apple', 'Watermelon', 'Mango'}
>>> 'Orange' in fruits
True
>>> 'Onion' in fruits
False
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a
{'c', 'r', 'b', 'a', 'd'}
>>> a - b
{'r', 'b', 'd'}
>>> a | b
{'c', 'l', 'd', 'b', 'z', 'r', 'm', 'a'}
>>> a & b
{'c', 'a'}
>>> a ^ b
{'l', 'd', 'b', 'z', 'r', 'm'}
译者注:因集合是无序的,所以读者在执行相同代码时得到的结果顺序可能会略有不同
Python 中还支持集合推导式(set comprehension),参见如下代码:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
字典
字典(dictionary)是Python中的一种数据类型,它由键值对组成并包裹在大括号{}中。字典是无序的并通过键进行索引,且每个键必须是唯一的。这些键必须为不可变类型。元组在级包含字符串、数字或元组时可作为字典的键。
仅仅使用一对大括号{}会创建一个空的字典。字典的主要运算是使用某些键来存储值并通过给定的键来提取值。同样可以使用 del 来删除一个键值对。如果使用了已有的键进行存储,就会抹除该键原来关联的值。使用不存在的键来提取值会报错。以下是使用字典的一个小例子:
>>> student = {'Name':'John', 'Age':25}
>>> student['Address'] = 'Mumbai'
>>> student
{'Name': 'John', 'Address': 'Mumbai', 'Age': 25}
>>> student['Age']
25
>>> del student['Address']
>>> student
{'Name': 'John', 'Age': 25}
>>> list(student.keys())
['Name', 'Age']
>>> sorted(student.keys())
['Age', 'Name']
>>> 'Name' in student
True
>>> 'Age' not in student
False
自选的键值表达式配合字典推导式可用于创建字典:
>>> {x: x**2 for x in (4, 6, 8)}
{4: 16, 6: 36, 8: 64}
在键是简单的字符串时,使用关键字参数的方式指定键值对很更为容易:
>>> dict(John=25, Nick=27, Jack=28)
{'Nick': 27, 'Jack': 28, 'John': 25}
解析命令行参数
在这一部分中,我们将学习参数的解析以及用于解析参数的模块。
Python 中的命令行参数
我们可以在命令行中添加额外的参数来启动程序。Python的程序可通过命令行参数来启动。让我们来看看下面这个例子:
$ python program_name.py img.jpg
这里program_name.py和img.jpg都是参数。我们将使用模块来获取这些参数:
| 模块 | 用法 | Python版本 |
| optparse | 已淘汰 | < 2.7 |
| sys | 所有sys.argv中的参数 (基本) | 所有版本 |
| argparse | 创建一个命令行接口 | >= 2.3 |
| fire | 自动生成命令行接口(CLI) | All |
| docopt | 创建CLI接口 | >= 2.5 |
Sys.argv
sys模块用于访问命令行参数。len(sys.argv) 函数包含参数的数量。要打印所有的参数,只需执行str(sys.argv)。让们来看看下面这个例子:
# 01.py
import sys
print('Number of arguments: ', len(sys.argv))
print('Argument list: ', str(sys.argv))
# 运行
python3 01.py img
# 执行结果
Number of arguments: 2
Argument list: ['01.py', 'img']
决策制定
当我们想要在条件为true时执行一个代码时,就需要使用到决策制定了。if...elif...else语句在Python中用于决策制定。
Python的if语句语法
以下是if语句的语法:
if test expression:
statement(s)
这里,程序运行了test 表达式并仅在该表达式为true时才执行下面的语句。如果表达式为false,则不会执行语句。
Python中if语句的主体通过缩进来表示。语句主体通过缩进来表示第一行的开始,通过取消缩进表示主体的结束。我们来看看下面这个例子:
a = 10
if a > 0:
print(a, "is a positive number.")
print("This statement is always printed.")
a = -10
if a > 0:
print(a, "is a positive number.")
输出结果:
10 is a positive number.
This statement is always printed.
Python的if...else语句语法
在这一部分,我们将学习if..else 语句。else代码块仅在if条件为false时执行。参见如下代码:
if test expression:
if block
else:
else block
if..else语句运行test表达式,仅在test条件为true时运行主体内容。如果条件为false,else中的主体内容会被执行。缩进用于分割代码块。参见如下示例:
a = 10
if a > 0:
print("Positive number")
else:
print("Negative number")
输出结果:
Positive number
Python的if...elif...else语句语法
elif语句从多条语句中检查true值。只要运行的执为 true 就执行相应的代码块。参见如下代码:
if test expression:
if block statements
elif test expression:
elif block statements
else:
else block statements
elif是else if的简写,让我们可以检查多个表达式。如果if语句中的条件为false,它会检查下一个elif代码块的条件,以此类推。如果所有条件均为false,else中的主体内容会被执行。
if...elif...else中仅会根据条件执行其中一个代码块。if代码块仅能带有一个else代码块,但可以有多个elif代码块。我们来看看以下的示例:
a = 10
if a > 50:
print("a is greater than 50")
elif a == 10:
print("a is equal to 10")
else:
print("a is negative")
输出结果:
a is equal to 10
循环
要处理脚本中的所有循环需求,Python支持两类循环:
- for 循环
- while 循环
下面我们就来学习for 循环和while 循环。
for循环
for循环遍历序列或其它可迭代对象中的每一项,并每次执行for代码块中的语句。参照如下代码:
for i in sequence:
for loop body
此处i 为在每次迭代时获取序列中各项值的变量。在到达序列最后一项之前循环会一直执行。下图中进行了描述:
for 循环的执行参见如下示例:
numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]
sum = 0
for i in numbers:
sum = sum + i
print("The sum is", sum)
输出结果:
The sum is 6
The sum is 11
The sum is 14
The sum is 22
The sum is 26
The sum is 28
The sum is 33
The sum is 37
The sum is 48
range()函数
Python的range()函数会生成一个数字的序列。例如,range(10)会生成0到9的数字(共10个数字)。
我们还可以定义起始、结束和步长来作为参数,这时range()函数如下所示:
range(start, stop, step size).
如未设置步长默认为1。
使用range()函数的 for 循环示例如下:
for i in range(5):
print("The number is", i)
输出结果:
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
while循环
while是一个在测试表达式为true时不停遍历代码块的循环语句。我们在不知道要迭代多少次时使用这一循环。参见如下代码:
while test_expression:
while body statements
在while循环中,我们首先检查测试表达式。while仅在这个测试表达式为true时执行。在一个迭代后,会重新对表达式进行检查,并在表达式运行值为false前不停重复这一过程。下图中进行了描述:
执行 while 循环以下为while循环的示例:
a = 10
sum = 0
i = 1
while i <= a:
sum = sum + i
i = i + 1
print("The sum is", sum)
运行结果:
The sum is 1
The sum is 3
The sum is 6
The sum is 10
The sum is 15
The sum is 21
The sum is 28
The sum is 36
The sum is 45
The sum is 55
迭代器
Python中的迭代器是可进行迭代的对象。这个对象会返回数据,每次返回一个元素。Python的迭代器对象实现了两个方法:iter()和next()。大多数情况下迭代器在循环、生成器和推导式中实现。
下例中,我们使用了next()函数,它会遍历所有的元素。在到达最后且没有更多数据返回时,会抛出StopIteration,如下例所示:
numbers = [10, 20, 30, 40]
numbers_iter = iter(numbers)
print(next(numbers_iter))
print(next(numbers_iter))
print(numbers_iter.__next__())
print(numbers_iter.__next__())
next(numbers_iter)
输出结果:
10
20
30
40
Traceback (most recent call last):
File "test.py", line 10, in <module>
next(numbers_iter)
StopIteration
生成器
我们可以使用Python生成器来创建迭代器。Python中生成器是返回一个可以迭代对象的函数。
如何在Python中创建生成器
在Python中创建生成器非常容易。我们可以定义一个函数,使用yield语句来代替return语句即可创建生成器。如果函数中至少包含一个yield语句,它就变成了一个生成器函数。yield和return语句会从函数中返回某些值。以下为示例:
def my_gen():
n = 1
print("This is printed first")
yield n
n += 1
print("This is printed second")
yield n
n += 1
print("This is printed at last")
yield n
for item in my_gen():
print(item)
输出结果:
This is printed first
1
This is printed second
2
This is printed at last
3
函数
函数时执行特定任务的一组语句。使用函数有助于将我们的程序分成更小的部分。函数可避免重复并让代码可以复用,因此让程序组织得更好。来看下面的语法:
def function_name:
statement(s)
参见如下示例:
def welcome(name):
print("Hello " + name + ", Welcome to Python Programming!")
welcome("John")
输出结果:
Hello John, Welcome to Python Programming!
return语句
return语句用于退出函数。参见如下的语法:
return [expression_list]
这个语句可能包含返回一个值的表达式。如果没有表达式,函数会返回None对象,如下例所示:
def return_value(a):
if a >= 0:
return a
else:
return -a
print(return_value(2))
print(return_value(-4))
输出结果:
2
4
Lambda函数
Python中匿名函数是未定义函数名的函数,称为lambda函数,使用关键字lambda进行定义。在需要短暂使用一个函数时我们使用这类函数。
lambda函数与内置的函数共同使用,如filter()和map()。
filter()函数返回一个元素列表,并仅接收一个迭代值。以下为使用filter()的示例:
numbers = [10, 25, 54, 86, 89, 11, 33, 22]
new_numbers = list(filter(lambda x: (x%2 == 0), numbers))
print(new_numbers)
输出结果:
[10, 54, 86, 22]
在本例中,filter()接收一个lambda函数以及一个列表来作为参数。
map()函数在应用指定函数之后返回一个结果列表。下面我们来看看使用map()的示例:
my_list = [1, 5, 4, 6, 8, 11, 3, 12]
new_list = list(map(lambda x: x * 2, my_list))
print(new_list)
输出结果:
[2, 10, 8, 12, 16, 22, 6, 24]
这里,map()函数接收一个lambda函数和一个列表。
模块
模块只是包含Python语句和定义的文件。一个包含Python代码的文件(如sample.py)称为一个模块,并且模块名应为sample。使用模块,我们可以大型的程序分解成更小和有组织的程序。模块的一个重要特性是复用性。我们无需在不同程序中拷贝经常使用到的函数定义,而是将它们定义在一模块中,然后需要使用时进行导入。
我们来创建一个模块并导入。我们将创建两个脚本:sample.py和add.py。然后在add.py中导入sample模块。现在将如下代码保存到sample.py文件中。我们来看看下面这个示例:
# sample.py
def addition(num1, num2):
result = num1 + num2
return result
这里我们在名为sample的模块中定义了一个函数addition()。该函数接收两个数值并返回和。这样我们就创建了一个模块。我们可以在任意Python程序中导入该模块。
导入模块
在创建模块后,我们来学习如何导入这一模块。上例中我们创建了一个sample模块。现在我们就在add.py脚本中导入sample模块:
# add.py
import sample
sum = sample.addition(10, 20)
print(sum)
输出结果:
30
总结
在本章中,我们概览了Python脚本语言。学习了如何安装Python以及各种工具。我们还学习了Python解释器以及如何使用它。我们学习了Python支持的数据类型、变量、数值和字符串、决策制定语句和Python中的循环语句。我们还学习了函数以及如何在脚本中使用函数,模块以及如何创建和导入模块。
在下一章Python脚本调试和性能测试中,我们将学习Python的调试技巧、错误处理(异常处理)、调试器工具、调试基本的程序崩溃、程序性能和用时测试以及加快程序运行。
问题
- 什么是迭代器和生成器?
- 列表是否可变?
- Python中的数据结构是什么?
- 如何说列表中的值?
- 什么是模块?
扩展阅读
Python的所有文档可通过官方网站获取。
还可以阅读如下图书:Learn Python Hard Way和Byte of Python来学习 Python 的基础知识。
本文首发地址:Alan Hou 的个人博客