Python 数据分析工具包(一)
一、熟悉 Python
Python 是一种开源编程语言,由荷兰程序员吉多·范·罗苏姆创建。Python 以英国喜剧团体 Monty Python 命名,是一种高级、解释型、开源语言,是当今世界上最受欢迎、发展最快的编程语言之一。它也是数据科学和机器学习的首选语言。
在这一章中,我们首先介绍 Jupyter notebook——一个用 Python 运行代码的 web 应用程序。然后,我们将介绍 Python 中的基本概念,包括数据类型、操作符、容器、函数、类和文件处理、异常处理,以及编写代码和模块的标准。
本书的代码示例是使用 Python 版本 3.7.3 和 Anaconda 版本 4.7.10 编写的。
技术要求
Anaconda 是一个开源平台,被 Python 程序员和数据科学家广泛使用。安装这个平台会安装 Python、Jupyter 笔记本应用程序和数百个库。下面是安装 Anaconda 发行版需要遵循的步骤。
图 1-1
安装 Anaconda
-
点击操作系统的安装程序,如图 1-1 所示。安装程序会下载到您的系统中。
图 1-2
发射 Jupyter
-
打开安装程序(上一步下载的文件)并运行它。
-
安装完成后,在开始菜单旁边的资源管理器(搜索栏)中键入“jupyter notebook”或“jupyter”打开 Jupyter 应用程序,如图 1-2 (针对 Windows OS 显示)。
请按照以下步骤下载本书中使用的所有数据文件:
-
选择绿色的“代码”菜单,并从该菜单的下拉列表中单击“下载 ZIP”
-
从下载的 zip 文件夹中提取文件,并将这些文件导入到 Jupyter 应用程序中
现在我们已经安装并启动了 Jupyter,让我们在下一节了解如何使用这个应用程序。
开始使用 jupiter 笔记本
在讨论 Jupyter 笔记本的本质之前,让我们先来讨论一下什么是集成开发环境(IDE)。IDE 集合了编程中涉及的各种活动,包括编写和编辑代码、调试和创建可执行文件。它还包括自动完成(完成用户想要键入的内容,从而使用户能够专注于逻辑和解决问题)和语法突出显示(突出显示语言的各种元素和关键字)等功能。除了 Jupyter,还有很多 Python 的 ide,包括 Enthought Canopy、Spyder、PyCharm 和 Rodeo。Jupyter 成为数据科学社区中无处不在、事实上的标准有几个原因。这些优势包括易于使用和定制、支持多种编程语言、平台独立性、方便访问远程数据,以及将输出、代码和多媒体结合在一个屋檐下的好处。
JupyterLab 是 Jupyter 笔记本的 IDE。Jupyter 笔记本是在用户机器上本地运行的网络应用程序。它们可用于加载、清理、分析和建模数据。您可以在 Jupyter 笔记本中添加代码、公式、图像和降价文本。Jupyter 笔记本有两个用途,一是运行您的代码,二是作为一个平台,展示您的工作并与他人分享。让我们看看这个应用程序的各种特性。
图 1-4
Jupyter 单元格中的简单代码语句
-
输入并执行代码
在笔记本的第一个单元格内点击,输入一行简单的代码,如图 1-4 所示。从“单元格”菜单中选择运行单元格来执行代码,或者使用快捷键 Ctrl+Enter 。
图 1-3
创建新的 Jupyter 笔记本
-
打开仪表板
在“开始”菜单旁边的搜索栏中键入“jupyter notebook”。这将打开 Jupyter 仪表板。仪表板可用于创建新笔记本或打开现有笔记本。
-
创建新笔记本
在 Jupyter 仪表盘右上角选择 New 创建一个新的 Jupyter 笔记本,然后在出现的下拉列表中选择 Python 3 ,如图 1-3 所示。
图 1-5
将模式更改为降价
-
添加降价文本或标题
在新的单元格中,通过选择如图 1-5 所示的 Markdown 或者按键盘上的 Esc+M 键来改变格式。您也可以通过从如下所示的下拉列表中选择标题或按快捷键 Esc+(1/2/3/4)来为 Jupyter 笔记本添加标题。
图 1-6
更改文件的名称
-
重命名笔记本
点击笔记本默认名称,输入新名称,如图 1-6 所示。
您也可以通过选择文件➤重命名来重命名笔记本。
图 1-7
下载 Jupyter 笔记本
-
保存笔记本
按 Ctrl+S 或选择文件➤保存和检查点。
-
下载笔记本
您可以通过电子邮件或共享您的笔记本,方法是使用选项文件➤下载为➤笔记本(。ipynb) ,如图 1-7 所示。
jupiter 中的快捷方式和其他功能
让我们来看看 Jupyter 笔记本的一些关键特性,包括快捷键、制表符补全和魔法命令。
表 1-1 给出了一些在 Jupyter 笔记本中常见的图标、相应的菜单功能和键盘快捷键。
表 1-1
Jupyter 笔记本工具栏功能
|工具栏中的图标
|
功能
|
键盘快捷键
|
菜单功能
|
| --- | --- | --- | --- |
| | 保存 Jupyter 笔记本 | Esc+s | 文件➤另存为 |
|
| 向 Jupyter 笔记本添加新单元格 | Esc+b (在当前单元格下方增加一个单元格),或者 Esc+a (在当前单元格上方增加一个单元格) | 在上方插入➤插入单元格或在下方插入➤插入单元格 |
|
| 剪切选定的单元格 | Esc+x | 编辑➤剪切单元格 |
|
| 复制选定的单元格 | Esc+c | 编辑➤复制单元格 |
|
| 将一个单元格粘贴到另一个选定单元格的上方或下方 | Esc+v | 编辑上方的➤粘贴单元格或编辑下方的➤粘贴单元格 |
|
| 运行给定的单元 | Ctrl+Enter (运行选中的单元格); Shift+Enter (运行选中单元格并插入新单元格) | 细胞➤运行选定的细胞 |
|
| 中断内核 | Esc+ii | 内核➤中断 |
|
| 重启内核 | Esc+00 | 内核➤重启 |
如果您不确定使用哪个快捷键,请进入:帮助➤快捷键,如图 1-8 所示。
图 1-8
Jupyter 中的帮助菜单
常用的键盘快捷键包括
-
Shift+Enter 运行当前单元格中的代码,移动到下一个单元格。
-
Esc 离开单元格。
-
Esc+M 将单元格的模式更改为“降价”模式。
-
Esc+Y 将单元格的模式改为“编码”。
制表符结束
这是一个可以用在 Jupyter 笔记本上的功能,帮助你完成正在编写的代码。使用制表符补全可以加快工作流程,减少错误,并快速补全函数名,从而减少打字错误,使您不必记住所有模块和函数的名称。
例如,如果您想要导入 Matplotlib 库,但不记得拼写,您可以键入前三个字母 mat,然后按 Tab。您会看到一个下拉列表,如图 1-9 所示。库的正确名称是下拉列表中的第二个名称。
图 1-9
Jupyter 中的制表符结束
木星中使用的魔法命令
魔术命令是以一个或多个%符号开始的特殊命令,后面跟一个命令。以一个%符号开始的命令适用于单行代码,以两个%符号开始的命令适用于整个单元(单元内的所有代码行)。
一个常用的神奇命令,如下所示,用于在笔记本中显示 Matplotlib 图形。添加这个神奇的命令避免了为显示图形而单独调用 plt.show 函数的需要(Matplotlib 库在第七章中详细讨论)。
代码:
%matplotlib inline
神奇的命令,如 timeit ,也可以用来计时脚本的执行,如下所示。
代码:
%%timeit
for i in range(100000):
i*i
输出:
16.1 ms ± 283 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
既然您已经了解了使用 Jupyter 笔记本的基本知识,那么让我们开始学习 Python 并了解这种语言的核心方面。
Python 基础
在本节中,我们将熟悉 Python 的语法、注释、条件语句、循环和函数。
注释、打印和输入
在这一节中,我们将介绍一些基础知识,比如打印、从用户那里获得输入,以及添加注释来帮助他人理解您的代码。
评论
注释解释一行代码做什么,程序员用它来帮助其他人理解他们写的代码。在 Python 中,注释以#符号开始。
适当的间距和缩进在 Python 中至关重要。Java 和 C++等其他语言使用括号来括住代码块,而 Python 使用缩进四个空格来指定代码块。人们需要注意缩进以避免错误。像 Jupyter 这样的应用程序通常会注意缩进,并自动在代码块的开头添加四个空格。
印刷
打印功能将内容打印到屏幕或任何其他输出设备。
通常,我们将字符串和变量的组合作为参数传递给 print 函数。参数是包含在函数括号内的值,函数用它来产生结果。在下面的语句中,“你好!”是 print 函数的参数。
代码:
print("Hello!")
为了打印多行代码,我们在字符串的开头和结尾使用三重引号,例如:
代码:
print('''Today is a lovely day.
It will be warm and sunny.
It is ideal for hiking.''')
输出:
Today is a lovely day.
It will be warm and sunny.
It is ideal for hiking.
注意,在 Python 中我们不像其他语言那样使用分号来结束语句。
格式方法可以与打印方法结合使用,用于在字符串中嵌入变量。它使用花括号作为变量的占位符,这些变量作为参数传递给方法。
让我们看一个简单的例子,我们使用格式方法打印变量。
代码:
weight=4.5
name="Simi"
print("The weight of {} is {}".format(name,weight))
输出:
The weight of Simi is 4.5
在没有 format 方法的情况下,上述语句也可以重写如下:
代码:
print("The weight of",name,"is","weight")
请注意,只有 print 参数的字符串部分用引号括起来。变量名不在引号内。同样,如果在打印参数中有任何常量,它们也不会出现在引号中。在下面的示例中,一个布尔常量(True)、一个整数常量(1)和字符串组合在一个 print 语句中。
代码:
print("The integer equivalent of",True,"is",1)
输出:
The integer equivalent of True is 1
格式字段可以指定浮点数的精度。浮点数是带小数点的数字,小数点后的位数可以使用如下格式字段指定。
代码:
x=91.234566
print("The value of x upto 3 decimal points is {:.3f}".format(x))
输出:
The value of x upto 3 decimal points is 91.235
我们可以指定传递给方法的变量的位置。在这个例子中,我们使用位置“1”来引用参数列表中的第二个对象,使用位置“0”来指定参数列表中的第一个对象。
代码:
y='Jack'
x='Jill'
print("{1} and {0} went up the hill to fetch a pail of water".format(x,y))
输出:
Jack and Jill went up the hill to fetch a pail of water
投入
输入功能接受用户的输入。用户提供的输入被存储为类型为字符串的变量。如果您想对任何数字输入进行数学计算,您需要将输入的数据类型更改为 int 或 float,如下所示。
代码:
age=input("Enter your age:")
print("In 2010, you were",int(age)-10,"years old")
输出:
Enter your age:76
In 2010, you were 66 years old
Python 中输入/输出的进一步阅读: https://docs.python.org/3/tutorial/inputoutput.html
变量和常数
常量或文字是不变的值,而变量包含可以改变的值。我们不需要在 Python 中声明一个变量,也就是指定它的数据类型,不像 Java 和 C/C++等其他语言。我们通过给变量命名并赋值来定义它。根据该值,数据类型会自动分配给它。使用赋值运算符(=)将值存储在变量中。Python 中命名变量的规则如下:
-
变量名不能有空格
-
变量不能以数字开头
-
变量名只能包含字母、数字和下划线(_)
-
变量不能使用保留关键字的名称(例如,类、继续、中断、打印等)。是 Python 语言中预定义的术语,具有特殊含义,作为变量名无效)
经营者
以下是 Python 中一些常用的运算符。
算术运算符:取两个整数值或浮点值,执行一次运算,返回值。
Python 支持以下算术运算符:
-
**(指数)
-
%(模或余数),
-
//(商),
-
*(乘法)
-
-(减法)
-
+(加法)
操作顺序至关重要。括号优先于指数,指数优先于除法和乘法,乘法优先于加法和减法。设计了一个首字母缩略词——p . e . d . m . a . s .(请原谅我亲爱的萨莉阿姨)——可以用来记住这些运算的顺序,以了解算术表达式中首先需要应用哪个运算符。下面给出了一个例子:
代码:
(1+9)/2-3
输出:
2.0
在前面的表达式中,首先执行括号内的运算,得到 10,然后执行除法,得到 5,最后执行减法,得到最终输出 2。
比较操作符:这些操作符比较两个值,并评估为真或假值。Python 支持以下比较运算符:
-
:大于
-
:小于
-
< =:小于或等于
-
=:大于或等于
-
==:平等。请注意,这不同于赋值运算符(=)
-
!=(不等于)
逻辑(或布尔)运算符:类似于比较运算符,它们也评估为真或假值。这些运算符对布尔变量或表达式进行运算。Python 支持以下逻辑运算符:
-
and 运算符:使用该运算符的表达式只有在其所有子表达式都为真时,才计算为真。否则,如果它们中的任何一个为假,则表达式评估为假
下面显示了一个使用和操作符的例子。
CODE:
(2>1) and (1>3)Output:
False -
或运算符:使用了或运算符的表达式,如果表达式中的任何一个子表达式为真,则计算结果为真。如果表达式的所有子表达式都评估为 False,则该表达式评估为 False 。
下面显示了一个使用或操作符的例子。
CODE:
(2>1) or (1>3)Output:
True -
not 运算符:使用了 not 运算符的表达式,如果表达式为 False ,则计算结果为 True ,反之亦然。
下面是一个使用而不是运算符的例子。
CODE:
not(1>2)Output:
True
赋值运算符
这些运算符为变量或操作数赋值。以下是 Python 中使用的赋值运算符列表:
-
=(给变量赋值)
-
+=(将右边的值与左边的操作数相加)
-
-=(从左边的操作数中减去右边的值)
-
*=(将左边的操作数乘以右边的值)
-
%=(返回左边的操作数除以右边的值后的余数)
-
/=(返回左边的操作数除以右边的值后的商)
-
//=(只返回左边的操作数除以右边的值后的商的整数部分)
下面给出了一些使用这些赋值运算符的例子。
代码:
x=5 #assigns the value 5 to the variable x
x+=1 #statement adds 1 to x (is equivalent to x=x+1)
x-=1 #statement subtracts 1 from x (is equivalent to x=x-1)
x*=2 #multiplies x by 2(is equivalent to x=x*2)
x%=3 #equivalent to x=x%3, returns remainder
x/=3 #equivalent to x=x/3, returns both integer and decimal part of quotient
x//=3 #equivalent to x=x//3, returns only the integer part of quotient after dividing x by 3
恒等运算符(is 和 not is)
这些操作符检查两个对象是否相等,即两个对象是否指向同一个值,并根据它们是否相等返回一个布尔值( True/False )。在下面的示例中,三个变量" x" 、*、【y】*和 "z" 包含相同的值,因此,当比较" x "和" z "时,恒等运算符(是)返回 True 。
示例:
x=3
y=x
z=y
x is z
输出:
True
隶属运算符(in 和 not in)
这些操作符检查一个特定的值是否出现在一个字符串或一个容器中(像列表和元组,在下一章讨论)。如果值存在,操作符中的返回“真”,如果值不在字符串或容器中,操作符中的返回“真”。
代码:
'a' in 'and'
输出:
True
数据类型
数据类型是变量的类别或类型,基于它存储的值。
变量或常量的数据类型可以使用 type 函数获得。
代码:
type(45.33)
输出:
float
表 1-2 中给出了一些常用的数据类型。
表 1-2
Python 中的常见数据类型
|数据类型
|
数据类型
|
例子
|
| --- | --- | --- |
| 数字数据 | int :对于没有小数点的数字float :带小数点的数字 | #int``a=1``#float``b=2.4 |
| 顺序 | 序列存储多个值。Python 中的一些序列是:列表范围元组 | #tuple``a=(1,2,3)``#list``b=[1,2,3]``#range``c=range(5) |
| 字符或文本 | str 是用于存储引号内的单个字符或字符序列的数据类型 | #single character``X='a'``#multiple characters``x='hello world'``#multiple lines``x='''hello world``good morning''' |
| 布尔数据 | bool 是用于存储真值或假值的数据类型 | X=True``Y=False |
| 映射对象 | 字典是字典的数据类型(一个将键映射到值的对象) | x={'Apple':'fruit','Carrot':'vegetable'} |
代表日期和时间
Python 有一个名为 datetime 的模块,允许我们定义日期、时间或持续时间。
我们首先需要导入这个模块,这样我们就可以使用这个模块中可用的函数来定义一个日期或时间对象,使用下面的语句。
代码:
import datetime
让我们使用本模块中的方法来定义各种日期/时间对象。
日期对象
可以使用 date 方法定义由日、月和年组成的日期,如下所示。
代码:
date=datetime.date(year=1995,month=1,day=1)
print(date)
输出:
1995-01-01
注意, date 方法的所有三个参数——日、月和年——都是必需的。如果在定义一个日期对象时跳过这些参数中的任何一个,就会出现错误,如下所示。
代码:
date=datetime.date(month=1,day=1)
print(date)
输出:
TypeError Traceback (most recent call last)
<ipython-input-3-7da76b18c6db> in <module>
----> 1 date=datetime.date(month=1,day=1)
2 print(date)
TypeError: function missing required argument 'year' (pos 1)
时间对象
为了在 Python 中定义一个存储时间的对象,我们使用了 time 方法。
可以传递给此方法的参数可能包括小时、分钟、秒或微秒。注意,与日期方法不同,参数对于时间方法不是强制性的(它们可以被跳过)。
代码:
time=datetime.time(hour=12,minute=0,second=0,microsecond=0)
print("midnight:",time)
输出:
midnight: 00:00:00
日期时间对象
我们还可以使用 datetime 方法定义一个由日期和时间组成的 datetime 对象,如下所示。对于此方法,日期参数——日、月和年——是必需的,但时间参数(如小时、分钟等)是必需的。)可以跳过。
代码:
datetime1=datetime.datetime(year=1995,month=1,day=1,hour=12,minute=0,second=0,microsecond=0)
print("1st January 1995 midnight:", datetime1)
输出:
1st January 1995 midnight: 1995-01-01 12:00:00
时三角洲对象
一个 timedelta 对象代表一个特定的持续时间,并且是使用 timedelta 方法创建的。
让我们创建一个存储 17 天时间的 timedelta 对象。
代码:
timedelta1=datetime.timedelta(weeks=2,days=3)
timedelta1
输出:
datetime.timedelta(days=17)
在创建一个 timedelta 对象时,您还可以添加其他参数,如秒、分钟和小时。
可以将 timedelta 对象添加到现有的 date 或 datetime 对象中,但不能添加到 time 对象中
将持续时间(时间增量对象)添加到日期对象:
代码:
#adding a duration to a date object is supported
date1=datetime.date(year=1995,month=1,day=1)
timedelta1=datetime.timedelta(weeks=2,days=3)
date1+timedelta1
输出:
datetime.date(1995, 1, 18)
将持续时间(时间增量对象)添加到日期时间对象:
代码:
#adding a duration to a datetime object is supported
datetime1=datetime.datetime(year=1995,month=2,day=3)
timedelta1=datetime.timedelta(weeks=2,days=3)
datetime1+timedelta1
输出:
datetime.datetime(1995, 2, 20, 0, 0)
向时间对象添加持续时间会导致错误:
代码:
#adding a duration to a time object is not supported
time1=datetime.time(hour=12,minute=0,second=0,microsecond=0)
timedelta1=datetime.timedelta(weeks=2,days=3)
time1+timedelta1
输出:
TypeError Traceback (most recent call last)
<ipython-input-9-5aa64059a69a> in <module>
2 time1=datetime.time(hour=12,minute=0,second=0,microsecond=0)
3 timedelta1=datetime.timedelta(weeks=2,days=3)
----> 4 time1+timedelta1
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
延伸阅读:
了解有关 Python 日期时间模块的详细信息
https://docs.python.org/3/library/datetime.html
使用字符串
字符串是用引号括起来的一个或多个字符的序列(单引号和双引号都可以接受)。字符串的数据类型是 str。 Python 不支持字符数据类型,不像 Java 和 c 这样的老语言。即使是单个字符,如‘a’,‘b’,也存储为字符串。字符串在内部存储为数组,并且是不可变的(不能修改)。让我们看看如何定义一个字符串。
定义字符串
单行字符串可以用单引号或双引号来定义。
代码:
x='All that glitters is not gold'
#OR
x="All that glitters is not gold"
对于多行字符串,使用三重引号:
代码:
x='''Today is Tuesday.
Tomorrow is Wednesday'''
字符串操作
字符串可以使用各种函数,下面将解释其中一些函数。
-
查找字符串的长度: len 函数可用于计算字符串的长度,如下所示。
代码:
len('Hello')Output:
5 -
访问字符串中的单个元素:
可以使用索引运算符[]提取字符串中的单个字符。
CODE:
x='Python' x[3] Output : 'h' -
对字符串进行切片:切片是指提取对象的一部分或子集(在这种情况下,对象是字符串)。切片也可以用于其他可迭代对象,比如列表和元组,我们将在下一章讨论。冒号操作符用于切片,带有可选的开始、停止和步进索引。下面提供了一些切片的例子。
CODE:
x='Python' x[1:] #from second character to the end输出:
'ython' Some more examples of slicing:CODE:
x[:2] #first two characters. The starting index is assumed to be 0Output:
'Py'CODE:
x[::-1]#reversing the string, the last character has an index -1Output:
'nohtyP' -
理由:
为了向右侧或左侧添加空格,或者使字符串居中,使用了 rjust 、 ljust 或 center 方法。传递给这种方法的第一个参数是新字符串的长度,可选的第二个参数是用于填充的字符。默认情况下,空格用于填充。
代码:
'123'.rjust(5,"*")Output:
'**123' -
改变大小写:改变字符串的大小写,使用上或下的方法,如下图所示。
代码:
'COLOR'.lower()Output:
'color' -
检查字符串包含的内容:
为了检查字符串是以给定的字符开始还是结束,使用了 startswith 或 endswith 方法。
代码:
'weather'.startswith('w')Output:
True -
从字符串中删除空格:
要删除字符串中的空格,请使用 strip 方法(删除两端的空格)、rst strip(删除右端的空格)或 lstrip 方法(删除左端的空格)。下面显示了一个示例。
代码:
' Hello'.lstrip()Output:
'Hello' -
检查字符串的内容:
有几种方法可以检查一个字符串包含什么,比如
isalpha, isupper, isdigit, isalnum等等。只有当字符串中的所有字符都满足给定条件时,所有这些方法才返回“True”。代码:
'981'.isdigit()#to check for digitsOutput:
TrueCODE:
'Abc'.isupper() #Checks if all characters are in uppercase. Since all letters are not uppercase, the condition is not satisfiedOutput:
False -
连接字符串列表:
join 方法将一系列字符串组合成一个字符串。在 join 方法的左侧,我们提到了用于连接字符串的引号中的分隔符。在右边,我们传递单个字符串的列表。
代码:
' '.join(['Python','is','easy','to','learn'])Output:
'Python is easy to learn' -
拆分字符串:
*split* 方法的作用与 join 方法相反。它将一个字符串分解成一个单词列表,并返回这个列表。如果我们只传递一个单词给这个方法,它会返回一个只包含一个单词的列表,并且不会进一步分割字符串。
代码:
```py
'Python is easy to learn'.split()
```
Output:
```py
['Python', 'is', 'easy', 'to', 'learn']
```
条件语句
条件语句,顾名思义,计算一个条件或一组条件。在 Python 中, if-elif-else 构造用于此目的。Python 没有 switch-case 结构,这种结构在其他一些语言中用于条件执行。
条件语句以 if 关键字和表达式或要计算的条件开始。接下来是一个代码块,仅当条件评估为“真”时才执行;否则将被跳过。
else 语句(不包含任何条件)用于在 if 语句中提到的条件不满足时执行一段代码。 elif 语句用于评估特定条件。elif 语句的顺序很重要。如果 elif 语句之一评估为真,则后面的 elif 语句根本不执行。 if 语句也可以单独存在,不提及 else 或 elif 语句。
以下示例演示了 if-elif-else 构造。
代码:
#if-elif-else
color=input('Enter one of the following colors - red, orange or blue:')
if color=='red':
print('Your favorite color is red')
elif color=='orange':
print('Your favorite color is orange')
elif color=='blue':
print('Your favorite color is blue')
else:
print("You entered the wrong color")
输出:
Enter one of the following colors - red, orange or blue:pink
You entered the wrong color
条件语句可以嵌套,这意味着我们可以将一个条件语句(内部)放在另一个条件语句(外部)中。使用嵌套语句时,需要特别注意缩进。下面显示了一个嵌套的 if 语句的例子。
代码:
#nested conditionals
x=20
if x<10:
if x<5:
print("Number less than 5")
else:
print("Number greater than 5")
else:
print("Number greater than 10")
输出:
Number greater than 10
延伸阅读:查看更多关于如果声明: https://docs.python.org/3/tutorial/controlflow.html#if-statements
环
循环用于重复执行部分代码。代码块的一次执行称为一次迭代,循环通常会经历多轮迭代。Python 中使用了两种类型的循环——用于循环的和用于循环的*。*
While 循环
只要条件为“真”,当我们想要执行特定指令时,就会使用 while 循环。代码块执行后,执行将返回到代码块的开头。下面显示了一个示例。
代码:
#while loop with continue statement
while True:
x=input('Enter the correct color:')
if(x!='red'):
print("Color needs to be entered as red")
continue
else:
break
输出:
Enter the correct color:blue
Color needs to be entered as red
Enter the correct color:yellow
Color needs to be entered as red
Enter the correct color:red
在前面的示例中,第一条语句( while True )用于执行无限循环。一旦输入的用户名长度正确,break 语句就会在循环之外执行;否则,将向用户显示一条消息,要求输入正确长度的用户名。请注意,在代码块的最后一条语句之后,执行会自动转到循环的开头。
break 语句用于将控制置于循环之外。当我们想要跳出一个无限循环时,这是很有用的。
continue 语句的作用正好相反——它控制循环的开始。关键字 break 和 continue 可以用于循环和条件语句,比如 if/else 。
延伸阅读:
查看有关以下内容的更多信息:
for 循环
循环的用于执行一段代码预定的次数。循环的可用于任何类型的 iterable 对象,也就是说,可由循环用于运行重复实例或迭代的值序列。这些可迭代对象包括列表、元组、字典和字符串。
回路的通常也与范围功能一起使用。range 函数创建了一个 range 对象,另一个可迭代对象,它是一个等间距整数序列。考虑下面的例子,我们使用 for 循环计算前五个奇数的总和。
代码:
#for loop
sum=0
for i in range(1,10,2):
sum=sum+i
print(sum)
输出:
25
范围函数有三个参数:开始参数、停止参数和步进参数。这三个参数都不是强制性的。从 0 到 9(包括 0 和 9)的数字可以生成为范围(10) 、范围(0,10) 或*范围(0,10,1)。*默认开始参数为 0,默认步进参数为 1。
For 循环也可以嵌套(一个外循环和任意数量的内循环),如下所示。
代码:
#nested for loop
for i in 'abcd':
for j in range(4):
print(i,end=" ")
print("\n")
输出:
a a a a
b b b b
c c c c
d d d d
延伸阅读:查看更多关于 for 的声明: https://docs.python.org/3/tutorial/controlflow.html#for-statements
功能
一个函数可以被认为是一个“黑盒”(用户不需要关心函数的内部工作),它接受输入,处理输入,并产生输出。函数本质上是执行特定任务的语句块。
在 Python 中,使用 def 关键字定义函数。后面是函数名和一个或多个可选参数。参数是只存在于函数中的变量。函数中定义的变量具有局部作用域,这意味着不能在函数外部访问它们。它们也被称为局部变量。外部代码或函数不能操作函数中定义的变量。
一个函数可以有一个可选的返回值。返回值是由返回到主程序的函数产生的输出。调用函数意味着给函数输入(参数)来执行任务并产生输出。
函数的效用在于它们的可重用性。它们还有助于避免冗余和将代码组织成逻辑块。我们只需要给它提供运行指令所需的一组输入。可以重复调用一个函数,而不是手动输入相同的代码行。
例如,假设您想在给定的数字列表中找出质数。一旦你写了一个函数来检查一个整数是否是一个质数,你可以简单地将列表中的每个数字作为参数传递给函数并调用它,而不是为你想要测试的每个整数写相同的代码行。
代码:
def checkPrime(i):
#Assume the number is prime initially
isPrime=True
for j in range(2,i):
# checking if the number is divisible by any number between 2 and i
if i%j==0:
#If it is divisible by any number in the j range, it is not prime
isPrime=False
# This is the same as writing if isPrime==True
if isPrime:
print(i ,"is prime")
else:
print(i, "is not prime")
for i in range(10,20):
checkPrime(i)
输出:
10 is not prime
11 is prime
12 is not prime
13 is prime
14 is not prime
15 is not prime
16 is not prime
17 is prime
18 is not prime
19 is prime
延伸阅读:查看更多关于定义函数: https://docs.python.org/3/tutorial/controlflow.html#defining-functions
匿名或λ****函数使用λ关键字定义。它们是单表达式函数,提供了一种简洁的方法来定义函数,而无需将函数对象绑定到名称。这些函数被称为“匿名”的原因是它们不需要名字。考虑下面的例子,我们使用 lambda 函数来计算两个数的和。
代码:
(lambda x,y:(x+y))(5,4)
输出:
9
注意匿名函数的语法。它以关键字 lambda 开始,后面是参数(在本例中是‘x’和‘y’)。然后是冒号,冒号后是一个表达式,它被求值并返回。没有必要提到 return 语句,因为在这样的函数中有一个隐式的 return。请注意,该函数也没有名称。
语法错误和异常
语法错误是用户在编写代码时可能无意中犯下的错误,例如,拼写错误的关键字、没有缩进代码等等。另一方面,异常是程序执行过程中出现的错误。用户在运行程序时可能会输入不正确的数据。如果你想用一个数(比如说‘a’)除以另一个数(比如说‘b’),但是给分母(比如说‘b’)一个 0 的值,这将会产生一个异常。Python 中自动生成并显示给用户的异常可能无法清楚地表达问题。使用带有 try-except 构造的异常处理,我们可以构造一个用户友好的消息,使用户能够更好地纠正错误。
异常处理有两个部分。首先,我们将可能导致错误的代码放在一个 try 子句下。然后,在 except 子句中,我们尝试处理在 try 块中导致错误的任何原因。我们在 except 子句中提到异常类的名称,后面是我们处理错误的代码块。处理错误的一个简单方法是打印一条消息,告诉用户需要纠正的更多细节。
注意,所有异常都是从类 BaseException 派生的对象,并且遵循层次结构。
延伸阅读:Python 中异常的类层次结构可以在这里找到: https://docs.python.org/3/library/exceptions.html#exception-hierarchy
下面是一个简单的程序例子,有和没有异常处理。
while True:
try:
n=int(input('Enter your score:'))
print('You obtained a score of ',n)
break
except ValueError:
print('Enter only an integer value')
输出:
Enter your score(without a decimal point):abc
Enter only an integer value
Enter your score(without a decimal point):45.5
Enter only an integer value
Enter your score(without a decimal point):90
You obtained a score of 90
相同程序(无异常处理):
代码:
n=int(input('Enter your score:'))
print('You obtained a score of ',n)
输出:
Enter your score:ninety three
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-aa4fbda9d45f> in <module>
----> 1 n=int(input('Enter your score:'))
2 print('You obtained a score of ',n)
ValueError: invalid literal for int() with base 10: 'ninety three'
前面代码中有可能导致错误的语句是:int(input('Enter your score:'))。 int 函数需要一个整数作为参数。如果用户输入一个浮点或字符串值,就会产生一个 ValueError 异常。当我们使用 try-except 构造时, except 子句打印一条消息,要求用户纠正输入,使其更加明确。
使用文件
我们可以使用 Python 中的方法或函数来读写文件。换句话说,我们可以创建一个文件,向其中添加内容或文本,并使用 Python 提供的方法读取其内容。
这里,我们讨论如何读写逗号分隔值(CSV)文件。CSV 文件或逗号分隔文件是文本文件,是 Excel 电子表格的文本版本。
所有这些操作的功能都在 CSV 模块下定义。必须首先使用import csv语句导入这个模块,以使用它的各种方法。
从文件中读取
从 Python 中读取文件包括以下步骤:
-
使用
with open语句,我们可以打开一个现有的 CSV 文件,并将结果文件对象分配给一个变量或文件句柄(在下面的例子中命名为‘f’)。请注意,我们需要使用绝对路径或相对路径来指定文件的路径。之后,我们需要指定打开文件的模式。对于阅读,模式是“r”。如果我们不指定模式,默认情况下文件是打开读取的。 -
接下来是一段代码,使用 csv.reader 函数将文件内容存储在一个 read 对象中,其中我们将文件句柄 f 指定为一个参数。
-
但是,这个文件的内容不能通过这个 read 对象直接访问。我们创建一个空列表(在下面的例子中命名为‘contents ’),然后使用 for 循环逐行遍历我们在步骤 2 中创建的 read 对象,并将其追加到这个列表中。然后可以打印该列表,以查看我们创建的 CSV 文件的行。
代码:
#Reading from a file
import csv
with open('animals.csv') as f:
contents=csv.reader(f)
lines_of_file=[]
for line in contents:
lines_of_file+=line
lines_of_file
写入文件
写入文件包括以下步骤。
-
使用打开功能,打开一个现有的 CSV 文件,或者如果文件不存在,打开功能创建一个新文件。如果要覆盖内容或写入新文件,请用引号将文件名(带绝对路径)括起来,并将模式指定为“w”。如果您只想在现有文件中添加一些行,请使用“a”或“append”模式。由于我们不想在这种情况下覆盖,我们使用 append ('a ')模式打开文件。将它存储在一个变量或文件句柄中,并给它一个名字,比如说‘f’。
-
使用 csv.writer() 函数,创建一个 writer 对象来添加内容,因为我们不能直接写入 csv 文件。将变量(文件句柄)“f”作为参数传递给此函数。
-
对上一步中创建的 writer 对象调用 writerow 方法。传递给该方法的参数是要添加的新行(作为列表)。
-
打开系统上的 CSV 文件,查看更改是否已经反映出来。
代码:
#Writing to a file
with open(r'animals.csv',"w") as f:
writer_object=csv.writer(f,delimiter=",")
writer_object.writerow(['sheep','lamb'])
open 函数可用于打开文件的模式有:
-
" r ":以只读方式打开文件。
-
“w”:打开一个只写的文件。如果文件已经存在,它将覆盖该文件。
-
“a”:在文件末尾打开文件进行写入。它保留原始文件内容。
-
" w+":打开文件进行读写。
延伸阅读:查看更多关于用 Python 读写文件: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
Python 中的模块
模块是扩展名为. py 的 Python 文件。它可以被认为是物理图书馆的一部分。正如图书馆的每个部分(例如,小说、体育、健身)都包含类似性质的书籍一样,模块包含彼此相关的功能。例如, matplotlib 模块包含了所有与绘制图形相关的函数。一个模块也可以包含另一个模块。例如, matplotlib 模块包含一个名为 pyplot 的模块。Python 中有许多内置函数,它们是标准库的一部分,使用它们不需要导入任何模块。
可以使用 import 关键字,后跟模块名称来导入模块:
代码:
import matplotlib
您也可以使用关键字中的导入模块的一部分(子模块或函数)。这里,我们从数学模块导入余弦函数:
代码:
from math import cos
在 Python 中创建和导入定制模块需要以下步骤:
-
在“开始”菜单旁边的搜索栏中键入“idle”。Python shell 打开后,选择文件➤新文件创建一个新文件
-
创建一些功能相似的函数。作为一个例子,在这里,我们正在创建一个简单的模块,它创建了两个函数——sin _ angle 和 cos_angle。这些函数计算角度的正弦和余弦(以度为单位)。
CODE:
import math def sin_angle(x): y=math.radians(x) return math.sin(y) def cos_angle(x): y=math.radians(x) return math.cos(y) -
保存文件。这个目录是保存文件的地方,也是 Python 运行的目录。您可以使用以下代码获取当前工作目录:
CODE:
import os os.getcwd() -
使用 import 语句,导入并使用您刚刚创建的模块。
Python 增强提案(PEP)8–编写代码的标准
Python 增强提案(PEP)是一个技术文档,为 Python 语言中引入的新特性提供文档。PEP 文档有很多种类型,其中最重要的是 PEP 8。PEP 8 文档提供了用 Python 编写代码的风格指南。PEP 8 的主要重点是提供一套增强代码可读性的一致规则——任何阅读你的代码的人都应该能够理解你在做什么。你可以在这里找到完整的 PEP8 文档: https://www.python.org/dev/peps/pep-0008/
PEP8 中有几个针对准则不同方面的指南,其中一些概述如下。
-
缩进:缩进用来表示代码块的开始。在 Python 中,四个空格用于缩进。缩进时应避免使用制表符。
-
行长度:一行代码的最大字符长度是 79 个字符。对于注释,限制为 72 个字符。
-
在 Python 中命名不同类型对象的命名约定也在 PEP 8 中列出。应该使用短名称,并且可以使用下划线来提高可读性。对于命名函数、方法、变量、模块和包,使用小写(全部是小写字母)符号。对于常量,使用大写(全部大写)符号,对于类,使用 CapWords(两个单词都以大写字母开头,不用空格分隔)符号进行命名。
-
注释:建议使用以#开头并描述整个代码块的块注释。应该避免与代码行在同一行的行内注释,如下所示。如果要使用它们,它们应该用两个空格与代码隔开。
代码:
- 进口:
sum+=1 #incrementing the sum by 1
当导入一个模块以在代码中使用它时,避免通配符导入(使用*符号),如下所示。
代码:
from module import *
不应在同一行中导入多个包或类。
代码:
import a,b
它们应该在单独的行中导入,如下所示。
代码:
import a
import b
应尽可能使用绝对进口,例如:
代码:
import x.y
或者,我们可以使用这种符号来导入模块:
代码:
- 编码:用于在 Python 3 中编写代码的编码格式是 UTF-8
from x import y
摘要
-
Python 的语法不同于其他语言,如 Java 和 C,因为 Python 中的语句不以分号结尾,空格(四个空格)用于缩进,而不是花括号。
-
Python 有基本的数据类型,如 int 、 float 、 str 和 bool 等等,还有根据数据类型对变量进行操作的运算符(算术、布尔、赋值和比较)。
-
Python 有 if-elif-else 关键字用于语句的条件执行。它还有用于循环的和用于重复程序特定部分的 while 循环。
-
函数有助于重用部分代码并避免冗余。每个功能应该只执行一项任务。Python 中的函数是使用 def 关键字定义的。匿名函数或 ?? 函数为在一行中编写函数提供了一种快捷方式,无需将函数绑定到名称上。
-
模块是相似函数的集合,是一个简单的 Python 文件。除了作为标准库一部分的函数之外,任何作为外部模块一部分的函数都需要使用 import 关键字导入该模块。
-
Python 具有创建、读取和写入文本和 CSV 文件的功能。这些文件可以以各种模式打开,这取决于您是要读取、写入还是追加数据。
-
异常处理可用于处理程序执行过程中发生的异常。使用 try 和 except 关键字,我们可以处理程序中可能导致异常的部分。
-
PEP 8 为 Python 中一系列与编码相关的方面设定了标准,包括空格、制表符和空行的使用,以及命名和编写注释的约定。
下一章将深入探讨容器、列表、元组、字典和集合等主题。我们还讨论了一种称为面向对象编程的编程范式,以及如何使用类和对象来实现它。
复习练习
问题 1
使用嵌套循环计算数字 1 到 5 的阶乘。
问题 2
使用下列哪一项定义函数?
-
def 关键字
-
功能关键字
-
void 关键字
-
不需要关键字
问题 3
以下代码的输出是什么?
x=True
y=False
z=True
x+y+z
问题 4
编写一个 Python 程序来打印以下序列:
问题 5
使用正确的语法定义了这些变量中的哪一个?
-
1x=3 -
x 3=5 -
x -
x_3=5 -
x$4=5
问题 6
以下代码的输出是什么?(提示:id 函数返回一个对象的内存地址。)
str1="Hello"
str2=str1
id(str1)==id(str2)
问题 7
将字符串“123-456-7890”转换为格式“1234567890”。使用连接和拆分字符串功能。
问题 8
编写一个执行以下任务的函数(文件名作为参数传递):
-
创建一个新的文本文件,其名称作为参数传递给函数
-
向文件中添加一行文本(“Hello World”)
-
阅读文件的内容
-
再次打开文件,在第一行下面添加另一行(“这是下一行”)
-
重读文件并在屏幕上打印内容
答案
问题 1
解决方案:
#Question 1
for i in range(1,6):
fact=1
for j in range(1,i+1):
fact=fact*j
print("Factorial of number ",i," is:",fact)
问题 2
选项 Python 中的函数需要 def 关键字。
问题 3
输出:2
解释:布尔值“True”被视为值 1,“False”被视为值 0。对布尔变量应用加法运算符是有效的。
问题 4
解决办法
#question 4
l=range(6)
for i in l[::-1]:
print("*"*i)
print("\n")
问题 5
选项 4 是正确的。
让我们一个接一个地检查选项:
-
1x=3:不正确,因为变量不能以数字开头
-
x 3=5:不正确,因为变量名不能包含空格
-
x:不正确,因为变量需要初始值
-
x_3=5:正确;定义变量时,下划线是可接受的字符
-
x这样的特殊字符
问题 6
这两个字符串具有相同的值和内存地址。
输出:
True
问题 7
这个问题可以用一行代码解决——只需拆分字符串,将其转换为一个列表,然后将其连接回一个字符串。
代码:
"".join(list("123-456-7890".split("-")))
问题 8
解决方案:
#Question 8
def filefunction(name):
#open the file for writing
with open(name+".txt","w") as f:
f.write("Hello World")
#read and print the file contents
with open(name+".txt","r") as f:
print(f.read())
#open the file again the append mode
with open(name+".txt","a") as f:
f.write("\nThis is the next line")
#reread and print the lines in the file
with open(name+".txt","r") as f:
print(f.read())
filename=input("Enter the name of the file ")
filefunction(filename)
二、探索容器、类和对象
在这一章中,我们将继续学习 Python 中的其他一些基本概念——各种类型的容器、可用于每个容器的方法、面向对象的编程、类和对象。
容器
在前一章中,我们看到一个变量可以有类似于 int 、 float 、 str 等数据类型,但是只能保存一个值。容器是可以包含多个值的对象。这些值可以具有相同的数据类型,也可以具有不同的数据类型。Python 中的四个内置容器是:
-
列表
-
元组
-
字典
-
设置
容器也被称为可迭代的;也就是说,您可以访问或遍历给定容器对象中的每个值。
在下面的小节中,我们将更详细地讨论每个容器及其方法。
列表
列表包含一组按顺序存储的值。列表是可变的,也就是说,可以修改、添加或删除列表中的值,使其成为一个灵活的容器。
可以使用索引来访问单个列表项,索引是方括号中的整数,表示该项的位置。列表的索引从 0 开始。
现在让我们来看看如何定义和操作一个列表。
定义列表
可以通过给列表一个名称和一组用方括号括起来的值来定义列表。
代码:
colors=['violet','indigo','red','blue','green','yellow']
向列表添加项目
表 2-1 中说明了不同的方法可用于向列表添加值。在前面的代码中创建的“颜色”列表用于下表给出的示例中。
表 2-1
向列表中添加项目
|方法
|
描述
|
例子
|
| --- | --- | --- |
| 附加 | 在列表末尾添加一项。该方法只接受一个值作为参数。 | 代码:colors.append('white')``#the value 'white' is added after the last item in the 'colors' list |
| 插入 | 在给定位置或索引处添加一项。这个方法有两个参数——索引和要添加的值。 | 代码:colors.insert(3,'pink')``#the value 'pink' is added at the fourth position in the 'colors' list |
| 扩展 | 在给定列表的末尾添加多个元素(作为一个列表)。该方法将另一个列表作为参数。 | 代码:colors.extend(['purple','magenta'])``#values 'purple' and 'magenta' added at the end of the 'colors' list |
从列表中删除元素
正如有多种方法可以向列表中添加项目一样,也有多种方法可以从列表中删除值,如表 2-2 中所述。请注意,每种方法一次只能删除一个项目。
表 2-2
从列表中删除项目
|方法
|
描述
|
例子
|
| --- | --- | --- |
| 的 | 关键字删除给定位置的项目。 | 代码:del colors[1]``#removes the second item of the 'colors' list |
| 移除 | 当已知要移除的项的名称,但不知道其位置时,使用此方法。 | 代码:colors.remove('white')``#removes the item 'white' from the 'colors' list |
| 流行 | 此方法移除并返回列表中的最后一项。 | 代码:colors.pop()``#removes the last item and displays the item removed |
查找列表中对象的索引(位置)
index 方法用于找出列表中特定项或值的位置(或索引),如以下语句所示。
代码:
colors.index('violet')
输出:
0
计算列表长度
len 函数返回列表中的项目数,如下所示。列表的名称作为参数传递给这个函数。注意 len 是一个函数,不是一个方法。方法只能用于对象。
代码:
len(colors)
输出:
7
排序列表
sort 方法对列表中的值进行升序或降序排序。默认情况下,此方法按升序对项目进行排序。如果列表包含字符串,则按字母顺序进行排序(使用每个字符串的第一个字母),如下所示。
代码:
colors.sort()
colors
输出:
['blue', 'green', 'purple', 'red', 'violet', 'white', 'yellow']
请注意,列表必须是同类的(列表中的所有值都应该是相同的数据类型),排序方法才能起作用。如果列表包含不同数据类型的项目,应用 sort 方法会导致错误。
如果您想按相反的字母顺序对元素进行排序,您需要添加 reverse 参数,并将其设置为“True”,如下所示。
代码:
colors.sort(reverse=True)
colors
输出:
['yellow', 'white', 'violet', 'red', 'purple', 'green', 'blue']
请注意,如果您只想颠倒列表中项目的顺序,而不想对项目进行排序,您可以使用 reverse 方法,如下所示。
代码:
colors=['violet','indigo','red','blue','green','yellow']
colors.reverse()
colors
输出:
['yellow', 'green', 'blue', 'red', 'indigo', 'violet']
延伸阅读:
查看更多可用于列表的方法:
https://docs.python.org/3/tutorial/datastructures.html#more-on-lists
切片列表
当我们从列表中创建切片时,我们通过从列表中选择特定的值,基于它们的位置或者通过使用一个条件,来创建原始列表的子集。列表切片的工作方式类似于字符串切片,我们在上一章已经研究过了。
为了使用索引创建切片,我们使用冒号操作符(:)并为需要选择的索引指定起始值和终止值。
如果我们在冒号前后都没有提供开始或停止值,则假定开始值是第一个元素的索引(0),而停止值是最后一个元素的索引,如下面的语句所示。
代码:
`colors[:]
输出:
['Violet', 'Indigo', 'Blue', 'Green', 'Yellow', 'Orange', 'Red']
如果我们使用步进索引,我们也可以使用冒号操作符两次。在下面的语句中,通过指定步长索引为 2 来提取列表的替代元素。
代码:
colors[::2]
输出:
['Violet', 'Blue', 'Yellow', 'Red']
就像字符串一样,列表遵循正索引和负索引。负索引(从–1 开始,是列表中最后一个元素的索引)从右到左工作,而正索引(从 0 开始,是列表中第一个元素的索引)从左到右工作。
下面显示了一个使用负索引的切片示例,其中我们从列表中的最后一个值开始提取替代元素。
代码:
colors[-1:-8:-2]
输出:
['Red', 'Yellow', 'Blue', 'Violet']
从现有列表创建新列表
从现有列表创建新列表有三种方法——列表综合、映射函数和过滤器函数——下面将对此进行解释。
- 列出理解
List comprehensions 提供了一种从现有列表创建新列表的简单而直观的方法。
让我们通过一个例子来理解这一点,在这个例子中,我们从前面创建的列表(“colors”)中创建一个新的列表(“colors1”)。此列表仅包含原始列表中包含字母“e”的项目。
代码:
colors1=[color for color in colors if 'e' in color]
colors1
输出:
['violet', 'red', 'blue', 'green', 'yellow']
列表理解的结构如图 2-1 所示。新列表中项目的输出表达式(' color ')首先出现。接下来是一个 for 循环来遍历原始列表(注意,其他循环,如 while 循环,在列表理解中不用于迭代)。最后,您可以使用 if/else 结构添加一个可选条件。
图 2-1
列表理解
如果我们试图使用循环和条件,在没有列表理解的情况下创建相同的列表,代码将会更加扩展,如下所示。
代码:
colors1=[]
for color in colors:
if 'e' in color:
colors1.append(color)
在使用列表理解时要记住的关键点是代码的可读性不应该受到损害。如果在创建新列表的过程中涉及到太多的条件表达式和循环,最好避免列表理解。
延伸阅读:查看更多关于列表理解: https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions
-
地图功能
map 函数用于通过在现有列表上应用用户定义的或内置的函数来创建新列表。 map 函数返回一个地图对象,我们需要应用 list 函数将其转换成一个列表。
The map function accepts two arguments:
-
要应用的函数
-
要应用该函数的列表
-
在下面的示例中,我们从“colors”列表创建一个新列表(“colors1”),将其元素转换为大写。使用了一个匿名(lambda)函数,后跟原始列表的名称。
代码:
colors=['violet','indigo','red','blue','green','yellow']
colors1=map(lambda x:x.upper(),colors)
colors1
输出:
<map at 0x2dc87148630>
该函数返回一个 map 对象,需要使用 list 函数将其转换为 list。
代码:
list(colors1)
输出:
- 过滤功能
['VIOLET', 'INDIGO', 'RED', 'BLUE', 'GREEN', 'YELLOW']
过滤器函数的语法类似于地图函数的语法。映射函数在应用后返回原始列表中的所有对象,而过滤器函数仅返回那些满足调用过滤器函数时指定的条件的项目。与 map 函数类似,我们传递两个参数(一个 lambda 函数或一个用户定义的函数,后跟列表的名称)。
在下面的例子中,我们从原始列表中创建一个列表,只保留那些少于五个字符的条目。
代码:
colors2=filter(lambda x:len(x)<5,colors)
list(colors2)
输出:
['red', 'blue']
现在让我们讨论如何同时遍历两个或更多的列表。
使用 zip 函数遍历多个列表
zip 函数提供了一种组合列表并在这些列表上联合执行操作的方法,如下所示。需要组合的列表作为参数传递给 list 函数。
代码:
#zip function and lists
colors=['Violet','Indigo','Blue','Green','Yellow','Orange','Red']
color_ids=[1,2,3,4,5,6,7]
for i,j in zip(colors, color_ids):
print(i,"has a serial number",j)
输出:
Violet has a serial number 1
Indigo has a serial number 2
Blue has a serial number 3
Green has a serial number 4
Yellow has a serial number 5
Orange has a serial number 6
Red has a serial number 7
zip 函数返回存储在“zip”类型对象中的元组列表。该对象的类型需要更改为列表类型才能查看元组。
代码:
list(zip(colors,color_ids))
输出:
[('Violet', 1),
('Indigo', 2),
('Blue', 3),
('Green', 4),
('Yellow', 5),
('Orange', 6),
('Red', 7)]
下一个函数, enumerate ,帮助我们访问列表中条目的索引。
访问列表中项目的索引
当你想访问一个给定列表中的对象及其索引时,枚举函数很有用。该函数返回一系列元组,每个元组包含该项及其索引。该函数的用法示例如下所示。
代码:
colors=['Violet','Indigo','Blue','Green','Yellow','Orange','Red']
for index,item in enumerate(colors):
print(item,"occurs at index",index)
输出:
Violet occurs at index 0
Indigo occurs at index 1
Blue occurs at index 2
Green occurs at index 3
Yellow occurs at index 4
Orange occurs at index 5
Red occurs at index 6
列表的连接
列表的连接,即我们组合两个或多个列表,可以使用'+'操作符来完成。
代码:
x=[1,2,3]
y=[3,4,5]
x+y
输出:
[1, 2, 3, 3, 4, 5]
我们可以连接任意数量的列表。请注意,串联不会修改任何被连接的列表。串联操作的结果存储在一个新的对象中。
extend 方法也可以用于列表的连接。与'+'操作符不同,扩展方法改变了原始列表。
代码:
x.extend(y)
x
输出:
[1, 2, 3, 3, 4, 5]
其他算术运算符,如-、*或/,不能用于组合列表。
为了找出两个包含数字的列表中元素的区别,我们使用 list comprehension 和 zip 函数,如下所示。
代码:
x=[1,2,3]
y=[3,4,5]
d=[i-j for i,j in zip(x,y)]
d
输出:
[-2, -2, -2]
元组
tuple 是 Python 中的另一个容器,和 list 一样,它按顺序存储项目。像列表中的项目一样,元组中的值可以通过它们的索引来访问。然而,元组的一些属性使其不同于列表,如下所述。
-
不变性:tuple 是不可变的,这意味着您不能添加、删除或更改 tuple 中的元素。另一方面,列表允许所有这些操作。
-
语法:定义元组的语法使用圆括号(或圆括号)将单个值括起来(与列表使用的方括号相比)。
-
速度:就访问和检索单个元素的速度而言,一个元组比一个列表表现得更好。
现在让我们学习如何定义一个元组以及可以用于元组的各种方法。
定义一个元组
元组可以定义为带括号或不带括号,如下面的代码所示。
代码:
a=(1,2,3)
#can also be defined without parenthesis
b=1,2,3
#A tuple can contain just a simple element
c=1,
#Note that we need to add the comma even though there is no element following it because we are telling the interpreter that it is a tuple.
就像列表一样,元组可以包含任何内置数据类型的对象,比如浮点、字符串、布尔值等等。
用于元组的方法
虽然元组不能更改,但有一些操作可以用元组来执行。这些操作解释如下。
元组中对象的频率
count 方法用于计算元组中给定值的出现次数:
代码:
x=(True,False,True,False,True)
x.count(True)
输出:
3
元组项目的位置/索引
index 方法可以用来查找一个元组中一个条目的位置。使用前面语句中创建的元组,让我们找到值“False”的出现。
代码:
x.index(False)
输出:
1
index 方法只返回该项第一次出现的位置。
元组解包
元组解包是提取元组中的单个值并将这些项中的每一项存储在单独的变量中的过程。
代码:
a,b,c,d,e=x
如果我们不知道元组中项的数量,我们可以使用“*_”符号将出现在第一个元素之后的元素解包到一个列表中,如下所示。
代码:
a,*_=x
print(a,_)
输出:
True [False, True, False, True]
一个元组的长度
可以使用 len 函数计算元组的长度:
代码:
len(x)
输出:
5
元组切片
可以对元组执行值的更小子集的切片或创建(在这方面类似于列表和字符串)。
下面是一个例子。
代码:
x[::-1]
输出:
(True, False, True, False, True)
元组的应用
下面是一些可以使用元组的场景。
- 用元组创建字典
我们将在下一节详细讨论字典,它是一个包含一组条目的容器(有一个映射到值的键)。元组可用于在创建字典时定义条目。
字典项是一个元组,可以使用 dict 方法将字典定义为一个元组列表,如下所示。
代码:
x=dict([('color','pink'),('flower','rose')])
x
输出:
- 多重分配
{'color': 'pink', 'flower': 'rose'}
如前所述,元组解包是将元组分成其组件的过程。这个原则可以用于在一行中初始化多个变量,如下所示。
代码:
#tuple unpacking
(a,b,c,d)=range(4)
print(a,b,c,d)
输出:
0 1 2 3
延伸阅读:在此查看更多关于元组: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences
字典
字典是包含一组条目的容器,每个条目将一个“键”映射到一个“值”。每个单独的项也称为键/值对。关于字典,还有其他一些需要注意的地方:
-
与列表和元组中的值不同,字典中的项不是按顺序存储的。
-
像列表一样,字典是可变的(即,可以对字典对象进行修改)。
-
花括号用于将字典中的条目括起来。
让我们了解如何定义一个字典以及可以用于字典对象的不同方法。
定义字典
字典被定义为一对花括号内的一组逗号分隔的键/值对,如下面的代码所示。
代码:
numbers={'English':'One','Spanish':'Uno','German':'Ein'}
numbers
输出:
{'English': 'One', 'Spanish': 'Uno', 'German': 'Ein'}
“英语”、“西班牙语”和“德语”构成了键,而“One”、“Uno”和“Ein”是字典中的值。
还可以使用 dict 函数来定义字典,正如我们在前面讨论元组时所解释的。这个函数的参数是一个元组列表,每个元组代表一个键/值对,如下所示。
numbers=dict([('English','One'),('Spanish','Uno'),('German','Ein')])
向字典添加条目(键/值对)
使用该键作为索引,可以向字典中添加一个新项,如下所示。
代码:
numbers['French']='un'
numbers
#A new key/value pair with the key as 'French' and value as 'un' has been added.
输出:
{'English': 'One', 'Spanish': 'Uno', 'German': 'Ein', 'French': 'un'}
访问字典中的关键字
keys 方法访问字典中的键:
代码:
numbers.keys()
输出:
dict_keys(['English', 'Spanish', 'German', 'French'])
访问字典中的值
values 方法访问字典中的值:
代码:
numbers.values()
输出:
dict_values(['One', 'Uno', 'Ein', 'un'])
访问字典中的所有键/值对
items 方法用于访问字典中的键/值对列表。
代码:
numbers.items()
输出:
dict_items([('English', 'One'), ('Spanish', 'Uno'), ('German', 'Ein'), ('French', 'un')])
访问单个值
可以使用给定键作为索引来检索对应于该键的值,如下所示。
代码:
numbers['German']
输出:
'Ein'
get 方法也可以用于检索值。该密钥作为参数传递给此方法,如下所示。
代码:
numbers.get('German')
输出与前面语句中获得的输出相同。
设置键的默认值
前面讨论的 get 方法也可以用来添加一个键/值对,并为一个键设置默认值。如果已经定义了键/值对,则默认值将被忽略。还有另一个方法, setdefault ,也可以用于这个目的。
注意, get 方法并不改变字典对象,而 setdefault 方法确保这些改变反映在对象中。
setdefault 方法的用法示例如下所示。
代码:
numbers.setdefault('Mandarin','yi')
numbers
输出:
{'English': 'One',
'Spanish': 'Uno',
'German': 'Ein',
'French': 'un',
'Mandarin': 'yi'}
正如我们所看到的,添加了一个新的键/值对。
下面显示了一个 get 方法的例子。
代码:
numbers.get('Hindi','Ek')
numbers
输出:
{'English': 'One',
'Spanish': 'Uno',
'German': 'Ein',
'French': 'un',
'Mandarin': 'yi'}
由 g et 方法设置的值不会添加到字典中。
清理字典
clear 方法从字典中删除所有的键/值对,换句话说,它清除字典的内容,而不从内存中删除变量。
#removing all the key/value pairs
numbers.clear()
输出:
{}
延伸阅读:查看更多关于词典的信息:
https://docs.python.org/3/tutorial/datastructures.html#dictionaries
设置
集合是一个容器,其中包含未排序或未索引的元素。集合的主要特征是它是由个唯一的元素组成的集合。请注意,如果我们在创建集合时添加重复的元素,Python 不会抛出错误。然而,当我们对集合执行操作时,所有重复的元素都被忽略,只考虑不同的元素。
设定定义
就像字典一样,集合是用花括号声明的,并且有无序的元素。然而,虽然可以使用关键字作为索引来访问字典中的值,但是不能通过索引来访问集合中的值。
以下是集合定义的示例:
代码:
a={1,1,2}
a
输出:
{1, 2}
正如我们从输出中看到的,重复值 1(存在于集合定义中)被忽略。
设定操作
表 2-3 中解释了可用于器械包的方法和功能。
延伸阅读:查看更多关于集: https://docs.python.org/3/tutorial/datastructures.html#sets
表 2-3
集合操作
|操作
|
方法/功能
|
例子
|
| --- | --- | --- |
| 求集合的长度 | 函数计算集合中元素的数量,只考虑不同的值。 | len(a) |
| 集合迭代 | for 循环可以遍历一个集合并打印它的元素。 | for x in a:``print(x) |
| 添加项目或值 | 使用添加方法可以将单个物品添加到器械包中。对于添加多个值,使用更新方法。 | a.add(3)``#or``a.update([4,5]) |
| 移除项目 | 可以使用移除或丢弃方法移除物品。 | a.remove(4)``# Or``a.discard(4)``#Note: When we try to delete an element that is not in the set, the discard method does not give an error, whereas the remove method gives a KeyError. |
既然我们已经涵盖了 Python 语言的所有要素——我们在前一章中学习的概念以及我们在本章中了解的关于各种容器及其方法的内容,我们需要决定使用哪种风格或编程范式。在各种编程范例中,包括过程式编程、函数式编程和面向对象编程,我们将在下一节讨论面向对象编程。
面向对象编程
面向对象编程(通常也称为“OOPS”)是作为传统编程方法的过程编程的替代方案出现的。
程序设计包括使用一系列步骤顺序执行程序。过程化编程的一个主要缺点是全局变量的存在容易受到意外操纵。OOPS 相对于过程化编程提供了几个优势,包括重用代码的能力、消除全局变量、防止未经授权的数据访问,以及提供管理代码复杂性的能力。
Python 遵循面向对象的范式。类和对象构成了面向对象编程的构造块。类提供了蓝图或结构,而对象实现了这个结构。使用 class 关键字定义类。
例如,假设您有一个名为“Baby”的类,其属性包括婴儿的名字、性别和体重。这个类的方法(或类中定义的函数)可以是婴儿执行的动作,如笑、哭和吃。实例/对象是类的实现,有自己的一组属性和方法。在这个例子中,每个婴儿都有其独特的特征(数据)和行为(功能)
一个类可以有一组属性或变量,可以是类变量,也可以是实例变量。类的所有实例共享类变量,而实例变量对于每个实例是唯一的。
让我们看看如何在 Python 中定义类,使用下面的例子:
代码:
#example of a class
class Rectangle:
sides=4
def __init__(self,l,b):
self.length=l
self.breadth=b
def area(self):
print("Area:",self.length*self.breadth)
my_rectangle=Rectangle(4,5)
my_rectangle.area()
输出:
Area: 20
class 关键字后跟一个类名和一个冒号。接下来,我们定义一个名为“sides”的类变量,并将其初始化为 4。该变量对该类的所有对象都是通用的。
在这之后,有一个设置或初始化变量的构造函数。注意构造函数的特殊语法——空格跟在关键字 def 后面,然后是两个下划线符号, init 关键字,再后面是两个下划线符号。
在一个类中定义的任何方法的第一个参数是 self 关键字,它引用该类的一个实例。然后是初始化参数“l”和“b”,它们指的是矩形的长度和宽度。这些值是在我们创建对象时作为参数提供的。实例变量“self.length”和“self . width”使用前面提到的参数进行初始化。接下来是另一个计算矩形面积的方法。记住,每当我们定义一个类的任何方法时,我们都需要添加 self 作为参数。
一旦定义了类,我们就可以定义这个类的一个实例,也称为对象。我们创建一个对象就像我们创建一个变量,给它一个名字,并初始化它。“my_rectangle”是创建的对象/实例的名称,后跟一个“=”符号。然后我们提到类的名字和在构造函数中使用的参数来初始化对象。我们正在创建一个长为 4,宽为 5 的矩形。然后我们调用 area 方法来计算面积,它计算并打印面积。
延伸阅读:查看更多关于 Python 中的类: https://docs.python.org/3/tutorial/classes.html
面向对象编程原则
面向对象编程的主要原则是封装、多态、数据抽象和继承。让我们来看看这些概念。
封装:封装是指将数据(类中定义的变量)与可以修改它的功能(方法)绑定在一起。封装还包括数据隐藏,因为类内定义的数据不会被类外定义的任何函数操纵。一旦我们创建了该类的一个对象,它的变量只能由与该对象相关联的方法(或函数)来访问和修改。
让我们考虑下面的例子:
代码:
class Circle():
def __init__(self,r):
self.radius=r
def area(self):
return 3.14*self.r*self.r
c=Circle(5)
c.radius #correct way of accessing instance variable
这里,Circle 类有一个实例变量 radius 和一个方法 area。变量 radius 只能使用该类的对象访问,而不能通过任何其他方式访问,如下面的语句所示。
代码:
c.radius #correct way of accessing instance variable
radius #incorrect, leads to an error
多态性
多态(一个接口,多种形式)提供了使用相同接口(方法或函数)的能力,而不管数据类型如何。
让我们使用 len 函数来理解多态性的原理。
代码:
#using the len function with a string
len("Hello")
输出:
5
代码:
#using the len function with a list
len([1,2,3,4])
输出:
4
代码:
#using the len function with a tuple
len((1,2,3))
输出:
3
代码:
#using the len function with a dictionary
len({'a':1,'b':2})
输出:
2
计算其参数长度的 len 函数可以接受任何类型的参数。我们将字符串、列表、元组和字典作为参数传递给该函数,该函数返回这些对象的长度。没有必要为每种数据类型编写单独的函数。
继承:继承指的是从父类创建另一个类的能力,称为子类。子类继承了父类的一些属性和功能,但也可能有自己的功能和变量。
下面演示了 Python 中继承的一个例子。
#inheritance
class Mother():
def __init__(self,fname,sname):
self.firstname=fname
self.surname=sname
def nameprint(self):
print("Name:",self.firstname+" "+self.surname)
class Child(Mother):
pass
父类称为“Mother”,其属性“firstname”和“surname”使用 init 构造函数方法初始化。名为“child”的子类继承自“Mother”类。当我们定义子类时,父类的名称作为参数传递。关键字 pass 指示 Python 不需要为子类做任何事情(这个类只是从父类继承一切,而不添加任何东西)。
然而,即使子类没有实现任何其他方法或添加任何额外的属性,关键字 pass 对于防止抛出任何错误是必不可少的。
延伸阅读:了解更多传承: https://docs.python.org/3/tutorial/classes.html#inheritance
数据抽象
数据抽象是只显示功能而隐藏实现细节的过程。例如,Whatsapp 的新用户只需要学习它的基本功能,如发送消息、附加照片和拨打电话,而不必学习编写该应用程序代码的开发人员如何实现这些功能。
在下面的例子中,我们声明了一个“Circle”类的对象并使用 area 方法计算面积,当我们调用 area 方法时,我们不需要知道面积是如何计算的。
class Circle():
def __init__(self,r):
self.r=r
def area(self):
return 3.14*self.r*self.r
circle1=Circle(3)
circle1.area()
输出:
28.259999999999998
摘要
-
容器是属于基本数据类型(如 int、float、str)的对象集合。Python 中有四个内置容器——列表、元组、字典和集合。
-
每个容器都有不同的属性,可以应用于容器的各种函数也各不相同,这取决于元素是否可以排序和更改(可变性)。列表是可变的和有序的,元组是不可变的和有序的,字典和集合是可变的和无序的。
-
Python 遵循面向对象编程的原则,如继承(从另一个类派生一个类)、数据抽象(仅呈现相关细节)、封装(将数据与功能绑定)和多态(使用多种数据类型的接口的能力)。
-
一个类包含一个构造函数(使用特殊的语法定义)、实例变量和操作这些变量的方法。所有方法都必须包含关键字 self 作为引用该类对象的参数。
在下一章,我们将学习 Python 如何应用于正则表达式和解决数学问题,以及用于这些应用的库。
复习练习
问题 1
如何将列表转换成元组,反之亦然?
问题 2
就像列表理解一样,字典理解是从现有条目创建字典的捷径。使用字典理解创建以下字典(从两个列表中,一个包含键(a–f),另一个包含值(1–6)):
{'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}
问题 3
下面哪个代码语句不是会导致错误?
-
'abc'[0]='d' -
list('abc')[0]='d' -
tuple('abc')[0]='d' -
dict([('a',1),('b',2)])[0]=3
问题 4
写一个程序,计算“乌云背后都有一线光明”这句话的元音数。
问题 5
以下代码的输出是什么?
x=1,2
y=1,
z=(1,2,3)
type(x)==type(y)==type(z)
问题 6
以下代码的输出是什么?
numbers={
'English':{'1':'One','2':'Two'},
'Spanish':{'1':'Uno','2':'Dos'},
'German':{'1':'Ein','2':'Zwei'}
}
numbers['Spanish']['2']
问题 7
考虑下面的字典:
eatables={'chocolate':2,'ice cream':3}
使用将另一个条目(关键字为“biscuit ”,值为 4)添加到这个字典中
-
如果语句
-
setdefault 方法
问题 8
创建一个包含从 1 到 20 的奇数的列表,并使用适当的 list 方法执行以下操作:
-
在末尾添加元素 21
-
在第四个位置插入数字 23
-
向此列表中添加另一个包含 1 到 20 的偶数的列表
-
找出数字 15 的索引
-
移除并返回最后一个元素
-
删除第 10 个元素
-
筛选此列表以创建所有数字小于或等于 13 的新列表
-
使用 map 函数创建一个新列表,其中包含列表中数字的方块
-
使用列表理解从现有列表创建新列表。如果是奇数,这个列表应该包含原始数字。否则它应该包含该数字的一半。
答案
问题 1
使用 list 方法将元组转换为列表:
list((1,2,3))
使用 tuple 方法将列表转换为元组:
tuple([1,2,3])
问题 2
代码:
#list containing keys
l=list('abcdef')
#list containing values
m=list(range(6))
#dictionary comprehension
x={i:j for i,j in zip(l,m)}
x
问题 3
正确选项:b 和 d
在选项 a 和 c 中,代码语句试图分别改变字符串和元组中的项目,它们是不可变的对象,因此这些操作是不允许的。在选项 b(列表)和 d(词典)中,允许项目分配。
问题 4
解决方案:
message="Every cloud has a silver lining"
m=message.lower()
count={}
vowels=['a','e','i','o','u']
for character in m:
if character.casefold() in vowels:
count.setdefault(character,0)
count[character]=count[character]+1
print(count)
问题 5
输出:
True
这三种方法都是公认的定义元组的方式。
问题 6
输出:
'Dos'
这个问题使用了嵌套字典(字典中的字典)的概念。
问题 7
解决方案:
eatables={'chocolate':2,'ice cream':3}
#If statement
if 'biscuit' not in eatables:
eatables['biscuit']=4
#setdefault method(alternative method)
eatables.setdefault('biscuit',4)
问题 8
解决方案:
odd_numbers=list(range(1,20,2))
#Add the element 21 at the end
odd_numbers.append(21)
#insert the number 23 at the 4th position
odd_numbers.insert(3,23)
#To this list, add another list containing even numbers from 1 to 20
even_numbers=list(range(2,20,2))
odd_numbers.extend(even_numbers)
#find the index of the number 15
odd_numbers.index(15)
#remove and return the last element
odd_numbers.pop()
#delete the 10the element
del odd_numbers[9]
#filter this list with all numbers less than or equal to 13
nos_less_13=filter(lambda x:x<=13,odd_numbers)
list(nos_less_13)
#use the map function to create a list containing squares
squared_list=map(lambda x:x**2,odd_numbers)
#use list comprehension for the new list
new_list=[x/2 if x%2==0 else x for x in odd_numbers]
new_list