世界各地的贡献者们正在将 freeCodeCamp 的技术教育资源翻译成不同语言,帮助人们免费学习编程,欢迎你加入教育公益活动:[参与 freeCodeCamp 开源社区翻译协作,帮助全世界人们用母语免费学习编程]
这本Python编程手册遵循“80/20定律”:使用20%的时间学习80%的内容。
我认为这种方法可以为学习者提供一个对Python全面的了解。
本手册并没有涵盖与Python相关的全部内容。它专注于这门编程语言的核心主题,并且试图简化那些复杂的内容。
我希望这本手册可以帮助您实现:学习Python的基础
注:您可以获取这本手册的PDF、ePub或者Mobi版本
Enjoy it!
Python正在逐步“占领”编程世界。它的受欢迎度和使用度正在以计算机历史中前所未有的方式实现增长。
Python在各种应用场景下都表现出色——Shell 脚本、自动化的任务和Web 开发只是其基本的应用。
Python是做数据分析和机器学习的首选语言,但是它也可以用来创建游戏或者在嵌入式设备上工作。
最重要的是,Python是世界上多所大学介绍计算机科学课程时选择的编程语言。
许多学生选择Python作为自己的第一门编程语言来学习。很多人正在学习Python,将来还会有更多人学习它。并且对于学习者中的大部分人来说,Python将是他们唯一需要的编程语言。
基于其独特的情况,Python在未来很有可能会更快地发展。
Python这门编程语言的特点是简单易上手、可读性强、非常直接、易于理解。
Python的生态系统非常庞大,可能需要一个图书馆才能容纳你所想象到的一切。
因为其直观的语法、庞大的社区和充满活力的生态系统,Python是一门适合编程初学者的高级编程语言。
Python也受到不同领域的专家赞赏。
从技术上讲,Python是一种解释型语言,它不像编译型语言(例如C或Java)那样具有中间编译阶段。
和许多解释型语言一样,Python是动态类型的,这意味着您不必声明所使用的变量的类型,并且变量不必为特定类型。
这有利有弊。特别是,您编写程序的速度会更快,但另一方面,您从工具中获得防止出现可能错误的帮助会较少。这意味着您只有在执行程序时才能发现某些问题。
Python支持多种编程范式,包括面向过程编程、面向对象编程和函数式编程。它足够灵活,可以适应不同的需求。
自从Python由Guido van Rossum于1991年创建后,它便越来越受欢迎——尤其是在过去5年中,正如这张Google趋势信息图所示:
开始Python编程非常容易。您只需从python.org选择适用于Windows、macOS或Linux的官方软件包安装,然后就可以开始使用Python了。
如果您是编程新手,我将会在接下来的内容中引导您从零开始成为一名Python程序员。
即使您目前是一名专门研究另一种编程语言的程序员,Python也值得您了解,因为我认为它只会继续发展壮大。
像C++和Rust这样相对于Python来说更“低级”的语言,对于专业程序员来说可能很棒,但是初学者如果从这两门语言开始学习编程,会感到畏惧,而且需要很长时间才能掌握。
另一方面,Python是一种适用于任何人——学生、使用Excel完成日常工作的人、科学家等等——的编程语言。
这是每个对编程感兴趣的人都应该首先学习的语言。
进入https://www.python.org,选择下载菜单(Downloads),然后选择您的操作系统,将出现一个带有官方软件包下载链接的面板:
请确保遵循关于您电脑所用的操作系统的特定说明。如果是在macOS上安装,您可以在https://flaviocopes.com/python-installation-macos/ 上找到详细指南。
您可以使用几种不同的方式来运行Python程序。
特别地,使用交互式环境(输入Python代码后,便立即执行它),和将Python程序保存到文件中,然后再执行它,这二者之间存在区别。
让我们从交互式环境开始。
如果您打开终端并输入python
,将在终端窗口上看到如下内容:
这是Python REPL(交互式解释器,即读取-评估-打印-循环)。
注意>>>
符号和之后的光标。,您可以在此处输入任何Python代码,然后按 enter
键运行它。
例如尝试定义一个新变量
name = "Flavio"
然后使用print()
打印name
的值:
print(name)
请注意:在REPL中,您也可以只输入
name
,然后按enter
键,您会看到name
的值。但是在写到文件中的程序里,如果这样做,您将看不到任何输出——您需要使用print()
代替这种写法。
您在此处编写的任何Python代码行都将立即执行。
输入quit()
可以退出这个Python REPL。
您可以使用Python自动安装的IDLE应用程序使用相同的交互式环境:
这对您来说可能更方便,因为与使用终端相比,使用鼠标可以更轻松地四处移动和复制/粘贴。
以上是Python默认附带的基础内容。不过我建议您安装IPython,它可能是您能找到的最好的Python命令行REPL应用程序。
使用下面的命令安装它
pip install ipython
上面的命令需要确保pip可执行文件的路径在您的环境变量中,安装好之后运行ipython
:
ipython
是另一个让您使用Python REPL的接口,并提供了一些不错的功能,如语法高亮、代码补全等等。
运行Python程序的第二种方法是将Python程序代码写入文件,例如program.py
:
然后用python program.py
运行它:
请注意,我们约定使用
.py
扩展名保存Python程序文件。
在这种情况下,程序作为一个整体被执行,而不是一次运行一行。而这就是我们运行程序的典型方式。
我们使用REPL进行快速的代码原型设计和学习。
在Linux和macOS上,也可以将Python程序文件转换为shell脚本,方法是在文件最前面加上一个特殊行,用来指示使用哪个可执行文件来运行它。
在我的系统上,Python解释器的路径是/usr/bin/python3
,所以我在第一行输入#!/usr/bin/python3
:
然后我可以对文件设置执行权限:
chmod u+x program.py
然后我可以使用下面的命令运行程序
./program.py
这在您编写与终端交互的脚本时特别有用。
我们还有许多其它方式可以运行Python程序。
一种方法是使用VS Code,尤其是Microsoft官方的Python扩展插件:
安装好此扩展插件后,您将可以使用Python代码自动补全、语法错误检查、自动格式化和使用pylint
进行代码检查,以及一些特殊命令,包括:
Python: Start REPL 用于在VS Code的集成终端中运行REPL:
Python: Run Python File in Terminal 用于在终端中运行当前文件:
Python: Run Current File in Python Interactive Window 在 Python 交互窗口中运行当前文件:
以及很多其它命令。只需打开命令面板(查看 -> 命令面板,或按下Cmd+Shift+P)并输入python
,即可查看所有与Python相关的命令:
另一种轻松运行Python代码的方法是repl.it,这是一个非常不错的网站,它提供了一个编程环境,您可以使用任何语言创建并运行程序,包括Python:
使用这个网站要先注册(免费注册),然后在“create a repl”下单击Python:
然后您将看到一个带有main.py
文件的编辑器,这样就已经准备好了编写Python代码:
一旦您写好一些代码后,单击“Run”就可以在窗口右侧运行它:
我认为repl.it很方便,因为:
我们一开始就应该讨论的一个关键主题是Python 2与Python 3。
Python 3于2008年被推出,其后作为主要的Python版本一直在被持续开发,而Python 2则通过错误修复和安全补丁进行维护,直到2020年初。
在那一天,对Python 2的支持停止。
许多程序仍然使用Python 2编写,并且组织仍在积极致力于这些程序,因为迁移到Python 3并非易事,升级这些程序需要大量工作。并且重要文件的大型迁移总是会引入新的bug。
但是对应新的代码程序,除非您必须遵守组织设置的强制使用Python 2的规则,否则应使用Python 3进行编写。
本书重点介绍 Python 3。
我们可以通过使用赋值运算符=
为“标签”赋值,从而创建一个新的Python变量。
在下面这个示例中,我们将字符串"Roger"
分配给变量name
:
name = "Roger"
下面是一个给变量age
赋值为数字的示例:
age = 8
一个变量的名字可以由字符、数字和_
下划线字符组成。变量名不能以数字开头。以下都是有效的变量名:
name1
AGE
aGE
a11111
my_name
_name
以下都是无效的变量名:
123
test!
name%
除此之外,任何输入都是有效的变量名,除非它是Python的关键字,如for
、if
、while
、import
等就是关键字。
无需记住它们,因为如果您使用其中任何一个关键字作为变量名,Python都会提醒您,并且您会逐渐视它们为Python语法的一部分。
我们可以_构造_任意一个有返回值的表达式代码,例如
1 + 1
"Roger"
另一方面,语句是对值的操作。例如,下面是2个语句:
name = "Roger"
print(name)
程序由一系列语句组成。每个语句占一行,但您可以使用分号在一行中包含多个语句:
name = "Roger"; print(name)
在Python程序中,井号之后的所有内容都被忽略,并被视为注释:
#this is a commented line
name = "Roger" # this is an inline comment
Python中的缩进是有意义的。
您不能像这样随意缩进:
name = "Flavio"
print(name)
对于其它一些语言,空格是没有意义的,但是在Python中,缩进很重要。
在上面这种情况下,如果您尝试运行这个程序,您会得到一个IndentationError: unexpected indent
错误,因为缩进有特殊的含义。
一个缩进中的所有内容属于一个块,如控制语句块或条件块,函数或类主体。我们稍后会看到更多关于这些内容的解释。
Python有几种内置类型。
如果您创建name
变量并为其分配值"Roger",则此变量现在自动表示String数据类型。
name = "Roger"
您可以使用type()
函数检查变量的类型,即将变量作为参数,然后将函数返回结果与str
进行比较:
name = "Roger"
type(name) == str # True
或者使用isinstance()
:
name = "Roger"
isinstance(name, str) # True
请注意,要在REPL之外查看
True
值,您需要将此代码包装在print()
中,但为了清楚起见,我避免使用它。
我们在这里使用了str
,但这种方法同样适用于其它数据类型。
首先,我们有数字。整数使用int
表示,浮点数(分数)的类型为float
:
age = 1
type(age) == int # True
fraction = 0.1
type(fraction) == float # True
您已经了解了如何从字面值创建某一类型的变量,如下所示:
name = "Flavio"
age = 20
Python自动从变量值检测数据类型。
您还可以通过向类构造器传递字面值或变量名,来创建特定类型的变量:
name = str("Flavio")
anotherName = str(name)
您还可以使用类构造器,将一种类型转换为另一种类型。Python将尝试转换为正确的值,例如从字符串中提取数字:
age = int("20")
print(age) # 20
fraction = 0.1
intFraction = int(fraction)
print(intFraction) # 0
这称为casting。当然,这种转换并不总是有效,具体取决于传递的值。如果您在上面的字符串中写了test
而不是20
,您会得到一个ValueError: invalid literal for int() with base 10: 'test'
错误。
这些只是基础的数据类型。Python中有更多其它数据类型:
complex
复数bool
布尔值list
列表tuple
元组range
范围dict
字典set
集合以及更多!
我们很快就会探索它们。
我们使用Python运算符来对值和变量进行运算操作。
我们可以根据它们执行操作的类型来划分运算符:
再加上一些其它有趣的运算符,比如is
和in
。
赋值运算符用于为变量赋值:
age = 8
或者将变量的值分配给另一个变量:
age = 8
anotherVariable = age
从Python 3.8开始,可以使用_海象运算符_:=
为变量赋值,同时该运算可作为另一个操作的一部分。例如在if
或循环的条件部分。这个稍后再谈。
Python有许多算术运算符:+
、-
、*
、/
(除法)、%
(取余)、**
(求幂)和 //
(向下取整除法) :
1 + 1 # 2
2 - 1 # 1
2 * 2 # 4
4 / 2 # 2
4 % 3 # 1
4 ** 2 # 16
4 // 2 # 2
请注意,操作数之间不需要空格,但加上空格有利于可读性。
-
也可用作一元运算符表示负号:
print(-4) # -4
+
也可用于连接字符串:
"Roger" + " is a good dog"
# Roger is a good dog
我们可以将赋值运算符与算术运算符结合起来:
+=
-=
*=
/=
%=
例子:
age = 8
age += 1
# age is now 9
Python定义了一些比较运算符:
==
!=
>
<
>=
<=
您可以使用这些运算符获取根据比较结果得到的布尔值(True
或False
):
a = 1
b = 2
a == b # False
a != b # True
a > b # False
a <= b # True
Python为我们提供了以下布尔运算符:
not
and
or
当使用True
或False
属性时,它们的作用类似于逻辑与、逻辑或和逻辑非,并且经常用于 if
条件表达式判断:
condition1 = True
condition2 = False
not condition1 # False
condition1 and condition2 # False
condition1 or condition2 # True
但是,请注意可能的混淆:
表达式中使用or
,则表达式的结果是第一个为非假值(假值:False
、0
、''
、[]
..)的操作数,否则返回最后一个操作数作为表达式的值。
print(0 or 1) # 1
print(False or 'hey') # 'hey'
print('hi' or 'hey') # 'hi'
print([] or False) # 'False'
print(False or []) # '[]'
Python文档将其(x or y)描述为如果x为假,则为y,否则为x
。(译者:or
碰到真值就停,没有真值就走到最后)
and
运算操作仅在第一个操作数为真时,才计算第二个操作数。因此,如果第一个操作数是假值(假值:False
、0
、''
、[]
..),它会返回那个操作数。否则,它就会计算第二个操作数:
print(0 and 1) # 0
print(1 and 0) # 0
print(False and 'hey') # False
print('hi' and 'hey') # 'hey'
print([] and False ) # []
print(False and [] ) # False
Python文档将其(x and y)描述为如果x为假,则为x,否则为y
。(译者:or
碰到假值就停,没有假值就走到最后)
一些运算符用于处理位和二进制数:
&
执行二进制与操作|
执行二进制或操作^
执行二进制异或操作~
执行二进制非操作<<
二进制左移操作>>
二进制右移操作一般很少使用位运算符,仅在非常特定的情况下使用,但是值得一提。
is
和in
is
被称为identity operator(验证运算符),用于比较两个对象,如果两者是同一个对象,则返回true。稍后将详细介绍对象。
in
被称为membership operator(成员运算符),用于判断一个值是否包含在一个列表或序列中。稍后将详细介绍列表和其他序列数据类型。
使用Python三元运算符,您可以快速定义条件语句。
假设您有一个函数,它将age
变量与18
进行比较,并根据结果返回True或False。
可以不这样写:
def is_adult(age):
if age > 18:
return True
else:
return False
您可以通过使用三元运算符这种方式来实现它:(译者:感觉这个例子不太好,因为这里写成return age > 18
会更好,换成这个例子return "age大于18" if age > 18 else "age小于等于18"
会更好理解一些)
def is_adult(age):
return True if age > 18 else False
首先定义条件为真的结果,然后判断条件,最后定义条件为假的结果:
<条件为真得到的结果> if <条件表达式> else <条件为假得到的结果>
Python中的字符串是用单引号或双引号括起来的一串字符:
"Roger"
'Roger'
您可以将字符串赋值给变量:
name = "Roger"
您可以使用+
运算符连接两个字符串:
phrase = "Roger" + " is a good dog"
您也可以使用+=
将一个字符串添加到另一个字符串后面:
name = "Roger"
name += " is a good dog"
print(name) # Roger is a good dog
您可以使用str
类构造函数将数字转换为字符串:
str(8) # "8"
这对于连接数字和字符串来说很重要:
print("Roger is " + str(8) + " years old") # Roger is 8 years old
当使用特殊语法定义时,字符串可以是多行的,将字符串括在一组3个引号中:
print("""Roger is
8
years old
""")
# double quotes, or single quotes
print('''
Roger is
8
years old
''')
字符串具有一组内置方法,例如:
isalpha()
检查字符串是否只包含字母字符,并且不为空字符串isalnum()
检查字符串是否只包含字母字符或数字字符,并且不为空isdecimal()
检查字符串是否只包含十进制字符,并且不为空lower()
获取字符串的小写版本islower()
检查字符串是否全为小写upper()
获取字符串的大写版本isupper()
检查字符串是否全为大写title()
获取字符串的“标题化”版本(译者:所有单词首字母大写)startsswith()
检查字符串是否以特定子字符串开头endswith()
检查字符串是否以特定子字符串结尾replace()
替换字符串的一部分split()
按特定分隔符拆分字符串strip()
修剪字符串中的空格join()
将字符串添加到另一个字符串(译者:实际上是将字符串添加到另一个可迭代对象生成的字符串中)find()
查找特定子字符串在字符串中的位置以及其它等等。
这些方法都不会改变原始字符串,它们将会返回一个新的、修改后的字符串。例如:
name = "Roger"
print(name.lower()) # "roger"
print(name) # "Roger"
您也可以使用一些全局函数来处理字符串。
这里我特别想到了len()
,它返回给您指定字符串的长度:
name = "Roger"
print(len(name)) # 5
in
运算符可以让您检查字符串是否包含某个子字符串:
name = "Roger"
print("ger" in name) # True
转义是一种将特殊字符添加到字符串中的方法。
例如,如何将双引号添加到被双引号包裹的字符串中?
name = "Roger"
"Ro"Ger"
将不起作用,因为Python会认为字符串以"Ro"
结尾。
方法是使用\
反斜杠字符转义字符串内的双引号:
name = "Ro\"ger"
这也适用于单引号\'
,以及其它特殊格式字符,如制表符\t
、换行符\n
和反斜杠\\
。
给定一个字符串,并给定一个索引(从0开始),您就可以使用方括号获取指定位置上的字符,从而获取特定内容:
name = "Roger"
name[0] # 'R'
name[1] # 'o'
name[2] # 'g'
使用负数将从末尾开始计数:
name = "Roger"
name[-1] # "r"
您还可以使用范围,即使用我们所说的切片:
name = "Roger"
name[0:2] # "Ro"
name[:2] # "Ro"
name[2:] # "ger"
Python提供了bool
类型,它可以有两个值:True
和 False
(首字母大写)。
done = False
done = True
布尔值对于条件控制结构特别有用,例如if
语句:
done = True
if done:
# run some code here
else:
# run some other code
在判断值为True
或False
时,如果该值不是bool
布尔类型,我们有一些取决于我们所检查值类型的规则:
0
以外,始终为True
False
False
您可以通过以下方式检查值是否为布尔值:
done = True
type(done) == bool # True
或者使用isinstance()
,需要传递2个参数:变量和bool
类:
done = True
isinstance(done, bool) # True
全局函数any()
在处理布尔值时也非常有用,当作为参数传递的可迭代对象(如列表)中的任意一个值是 True
时,它就会返回 True
(译者:类似or
):
book_1_read = True
book_2_read = False
read_any_book = any([book_1_read, book_2_read]) # True
全局函数all()
相类似,但是是当传递给它的所有值都是True
时,才返回 True
(译者:类似and
):
ingredients_purchased = True
meal_cooked = False
ready_to_serve = all([ingredients_purchased, meal_cooked]) # False
Python中的数字有3种类型:int
、float
和complex
。
整数使用int
表示,您可以使用字面值定义整数:
age = 8
您还可以使用int()
构造函数定义一个整数:
age = int(8)
您可以使用全局函数type()
检查变量是否为int
类型:
type(age) == int # True
浮点数(分数)的类型为float
,您可以使用字面值定义浮点数:
fraction = 0.1
或者使用float()
构造函数:
fraction = float(0.1)
您可以使用全局函数type()
检查变量是否为float
类型:
type(fraction) == float # True
复数属于complex
类型。
您可以使用字面值定义它们:
complexNumber = 2+3j
或者使用complex()
构造函数:
complexNumber = complex(2, 3)
一旦您定义了一个复数,您就可以得到它的实部和虚部:
complexNumber.real # 2.0
complexNumber.imag # 3.0
同样,您可以使用全局函数type()
检查变量是否为complex
类型:
type(complexNumber) == complex #True
您可以使用算术运算符对数字执行算术运算:+
、-
、*
、/
(除法)、%
(取余)、**
(求幂)和//
(向下取整除法):
1 + 1 # 2
2 - 1 # 1
2 * 2 # 4
4 / 2 # 2
4 % 3 # 1
4 ** 2 # 16
4 // 2 # 2
您还可以使用复合赋值运算符
+=
-=
*=
/=
%=
这样可以快速对变量执行运算操作:
age = 8
age += 1 # age: 9
有2个内置函数可以帮助处理数字:
abs()
返回一个数字的绝对值。
给定一个数字,round()
返回四舍五入到最接近整数的值:
round(0.12) # 0
您可以指定第二个参数来设置舍入到小数点的精度:
round(0.12, 1) # 0.1
Python标准库提供了其它几个数学实用函数和常量:
math
包提供通用的数学函数和常量cmath
包提供了处理复数的方法decimal
包提供了处理小数和浮点数的方法fractions
包提供了处理有理数的方法稍后我们将分别探讨其中的一些。
Python中无法强制改变的值是常量。
比较常用的是枚举:
class Constants(Enum):
WIDTH = 1024
HEIGHT = 256
并使用Constants.WIDTH.value
这样的表达获取每个值。
没有人可以重新分配该值。
否则,如果您想依赖命名约定(来定义常量),您可以遵守这个规则——声明大写的永远不应该改变的变量:
WIDTH = 1024
没有人会阻止您覆盖这个值,Python也不会阻止。(译者:全大写的变量表示不应改变的常量,这只是一种约定)
正如您将来会看到的,大多数Python代码都采用这种命名约定的写法。
枚举是绑定到常量值的可读名称。
要使用枚举,请从enum
标准库模块中导入Enum
:
from enum import Enum
然后您可以用这种方式初始化一个新的枚举:
class State(Enum):
INACTIVE = 0
ACTIVE = 1
这样做后,您可以引用作为常量的State.INACTIVE
和State.ACTIVE
。
现在,如果您尝试打印State.ACTIVE
,例如:
print(State.ACTIVE)
它不会返回1
,而是返回State.ACTIVE
。
枚举中分配的数字可以达到相同的效果:print(State(1))
将打印State.ACTIVE
。使用方括号符号State['ACTIVE']
也是如此。
但是,您可以使用State.ACTIVE.value
获取具体值。
您可以列出枚举的所有可能值:
list(State) # [<State.INACTIVE: 0>, <State.ACTIVE: 1>]
您可以获取总数:
len(State) # 2
在Python命令行程序中,您可以使用print()
函数向用户显示信息:
name = "Roger"
print(name)
我们也可以使用input()
接受来自用户的输入:
print('What is your age?')
age = input()
print('Your age is ' + age)
这种方法在运行时获取输入,这意味着程序(执行到input()
时)将停止执行,等待用户输入内容并按下enter
键。
您还可以在程序调用时接受输入并进行更复杂的输入处理,稍后我们将看到如何做到这一点。
这适用于命令行程序。其它类型的应用程序需要使用不同的方式来接受输入。
当您处理布尔值和返回布尔值的表达式时,您可以根据它们的值为True
或False
来采取不同的方式。
在Python中,我们使用if
语句来做到这一点:
condition = True
if condition == True:
# do something
当条件解析为True
时,就像上面的情况一样,if下面的代码块被执行。
什么是代码块?代码块是向右侧缩进一级(通常为4个空格)的部分:
condition = True
if condition == True:
print("The condition")
print("was true")
代码块可以由单行或多行组成,并在您移回到上一个缩进级别时结束:
condition = True
if condition == True:
print("The condition")
print("was true")
print("Outside of the if")
如果if
的条件测试结果为False
,结合if
则可以执行else
块:
condition = True
if condition == True:
print("The condition")
print("was True")
else:
print("The condition")
print("was False")
如果前面的if
检查是False
,您可以使用elif
执行另一个条件检查:
condition = True
name = "Roger"
if condition == True:
print("The condition")
print("was True")
elif name == "Roger":
print("Hello Roger")
else:
print("The condition")
print("was False")
如果condition
为False
并且name
变量的值为"Roger",则执行本例中的第二个代码块。
在一个if
语句中,您只可以进行一次if
和 else
检查,但可以进行多个elif
检查:
condition = True
name = "Roger"
if condition == True:
print("The condition")
print("was True")
elif name == "Roger":
print("Hello Roger")
elif name == "Syd":
print("Hello Syd")
elif name == "Flavio":
print("Hello Flavio")
else:
print("The condition")
print("was False")
if
和 else
也可以内联使用,这让我们可以根据条件返回一个值或另一个值。
例子:
a = 2
result = 2 if a == 0 else 3
print(result) # 3
列表是Python中一种基本的数据结构。
使用列表,您可以将多个值组合在一起,并使用一个名称引用它们。
例如:
dogs = ["Roger", "Syd"]
一个列表中可以保存不同数据类型的值:
items = ["Roger", 1, "Syd", True]
您可以使用in
运算符检查某个元素是否在列表中:
print("Roger" in items) # True
当然也可以定义空的列表:
items = []
您可以通过从零开始的索引引用列表中的元素:
items[0] # "Roger"
items[1] # 1
items[3] # True
使用相同的表示法,您可以更改存储在特定索引处的值:
items[0] = "Roger"
您还可以使用index()
:
items.index(0) # "Roger"
items.index(1) # 1
就像字符串(索引)一样,使用负索引将从末尾开始数:
items[-1] # True
您还可以使用切片提取列表的一部分:
items[0:2] # ["Roger", 1]
items[2:] # ["Syd", True]
使用全局函数len()
获取列表中包含的元素数目,这与我们用来获取字符串长度的方法相同:
len(items) # 4
您可以使用list的append()
方法将新元素添加到列表中:
items.append("Test")
或者使用extend()
方法:
items.extend(["Test"])
您还可以使用+=
运算符:
items += ["Test"]
# items is ['Roger', 1, 'Syd', True, 'Test']
注意:使用
extend()
或+=
不要忘记方括号。不要执行items += "Test"
或items.extend("Test")
,否则Python会在列表中添加4个单独的字符,即['Roger', 1, 'Syd', True, 'T'、'e'、's'、't']
使用remove()
方法删除元素:
items.remove("Test")
您可以添加多个元素:
items += ["Test1", "Test2"]
# or
items.extend(["Test1", "Test2"])
这些方法会将元素加到列表的末尾。
要在列表中间的特定索引处添加元素,请使用insert()
方法:
items.insert("Test", 1) # add "Test" at index 1
要在特定索引处添加多个项目,您需要使用切片:
items[1:1] = ["Test1", "Test2"]
# 译者:这里实际上是先删除再添加,就该例子来说,先删除[1:1]的元素(切片是左闭右开,所有[1:1]没有选中任何元素),再在删除的位置上添加
#。 比如s = [1,2,3]; s[0:2] = ['a', 'b', 'c']; --> 执行完前面两个语句,s就变为['a', 'b', 'c', 3]
使用sort()
方法对列表进行排序:
items.sort()
注意:sort()仅在列表包含可比较的值时才有效。例如,无法比较字符串和整数,如果您尝试(对元素之间不可比较的列表进行排序),您将看到到类似
TypeError: '<' not supported between 'int' and 'str'
的错误。
(针对字符串排序)sort()
方法首先排序大写字母,然后是小写字母。要解决此问题,请使用:
items.sort(key=str.lower)
(使用sort方法)排序会修改原始列表内容。为避免这种情况,您可以先复制列表
itemscopy = items[:]
或者使用全局函数sorted()
:
print(sorted(items, key=str.lower))
这将返回一个排好序的新列表,而不是修改原始列表。
元组是Python中另一种基本的数据结构。
它允许您创建不可变的对象组。这意味着一旦创建了元组,就无法修改它。您不能添加或删除元组中的元素。
元组的创建方式类似于列表,但是是使用括号而不是方括号:
names = ("Roger", "Syd")
元组是有序的,就像列表一样,所以您可以通过一个索引来获取具体位置的值:
names[0] # "Roger"
names[1] # "Syd"
您也可以使用index()
方法:
names.index('Roger') # 0
names.index('Syd') # 1
与字符串和列表一样,使用负索引将从末尾开始:
names[-1] # True
您可以使用函数len()
计算元组中的元素个数:
len(names) # 2
您可以使用in
运算符检查元素是否在元组中:
print("Roger" in names) # True
您还可以使用切片提取元组的一部分:
names[0:2] # ('Roger', 'Syd')
names[1:] # ('Syd',)
您可以使用全局函数sorted()
创建元组排好序的版本:(译者:请注意,元组没有sort方法,因为元组是不可改变的)
sorted(names)
您可以使用+
运算符从现有元组创建一个新元组:
newTuple = names + ("Vanille", "Tina")
字典是Python中非常重要的一种数据结构。
列表允许您创建值的集合,而字典允许您创建键/值对的集合。
这是有一个键/值对的字典示例:
dog = { 'name': 'Roger' }
键可以是任何不可变的值,例如字符串、数字或元组,该值可以是您想要的任何值。
一个字典可以包含多个键/值对:
dog = { 'name': 'Roger', 'age': 8 }
您可以使用此表示法访问单个键对应的值:
dog['name'] # 'Roger'
dog['age'] # 8
使用相同的表示法,您可以更改在特定索引(键)对应的值:
dog['name'] = 'Syd'
另一种方法是使用get()
方法,该方法可以添加默认值(译者:即字典中没有该键时返回的值):
dog.get('name') # 'Roger'
dog.get('test', 'default') # 'default'
pop()
方法检索键的值,然后从字典中删除该键/值对:
dog.pop('name') # 'Roger'
popitem()
方法检索并删除最后一个插入字典的键/值对:
dog.popitem()
您可以使用in
运算符检查键是否包含在字典中:
'name' in dog # True
使用keys()
方法获取字典中的键,并将结果传递给list()
构造函数:
list(dog.keys()) # ['name', 'age']
使用values()
方法获取字典中的值,使用items()
方法获取键/值对组成的元组:
print(list(dog.values()))
# ['Roger', 8]
print(list(dog.items()))
# [('name', 'Roger'), ('age', 8)]
使用全局函数len()
获取字典长度,这与获取字符串或列表的长度相同:
len(dog) # 2
您可以通过这种方式将新的键/值对添加到字典中:
dog['favorite food'] = 'Meat'
您可以使用del
语句从字典中删除键/值对:
del dog['favorite food']
要复制字典,请使用copy()方法:(译者:这种方式是浅拷贝)
dogCopy = dog.copy()
集合是Python另一个重要的数据结构。
可以说它像元组一样工作,但集合不是有序的,而且是可变的。
或者我们可以说它像字典一样工作,但它们没有键。
集合还有一个不可变的版本,称为frozenset
。
您可以使用以下语法创建集合:
names = {"Roger", "Syd"}
您将它们视为数学上的集合,会更好理解。
您可以求两个集合的交集:
set1 = {"Roger", "Syd"}
set2 = {"Roger"}
intersect = set1 & set2 # {'Roger'}
您可以创建两个集合的并集:
set1 = {"Roger", "Syd"}
set2 = {"Luna"}
union = set1 | set2
# {'Syd', 'Luna', 'Roger'}
您可以得到两个集合的差集:
set1 = {"Roger", "Syd"}
set2 = {"Roger"}
difference = set1 - set2 # {'Syd'}
您可以检查一个集合是否是另一个集合的超集(也即一个集合是另一个集合的子集):
set1 = {"Roger", "Syd"}
set2 = {"Roger"}
isSuperset = set1 > set2 # True
您可以使用全局函数len()
计算集合中的元素个数:
names = {"Roger", "Syd"}
len(names) # 2
您可以通过将集合传递给list()
构造函数来获取集合元素的列表:
names = {"Roger", "Syd"}
list(names) # ['Syd', 'Roger']
您可以使用in
运算符检查元素是否在集合中:
print("Roger" in names) # True
函数可以创建一组指令,我们在需要时运行这些指令。
函数在Python和其它许多编程语言中是必不可少的。它帮助我们创建有意义的程序,因为我们可以使用函数将程序分解为可管理的部分,并且促进了代码的可读性和重用性。
这是一个名为hello
的函数示例,它打印"Hello!":
def hello():
print('Hello!')
函数定义:有一个名称(hello
)和一个由一组指令组成的主体(即冒号后面的部分),主体在右侧缩进一级。
要运行这个函数,我们必须调用它。这是调用函数的语法:
hello()
我们可以调用这个函数一次或多次。
函数名hello
非常重要,它应该是描述性的,这样任何调用该函数的人都可以理解它的作用。
一个函数可以接受一个或多个参数:
def hello(name):
print('Hello ' + name + '!')
这种情况下,我们通过传递参数来调用函数
hello('Roger')
我们称_parameters_为函数定义中函数所接受的值(形参),称_arguments_为我们调用函数时所传递给函数的值(实参)。对这种区别感到困惑是很正常的。
如果(调用函数时)未指定参数,则参数可以具有默认值:
def hello(name='my friend'):
print('Hello ' + name + '!')
hello()
# Hello my friend!
以下是如何接受多个参数:
def hello(name, age):
print('Hello ' + name + ', you are ' + str(age) + ' years old!')
在这种情况下,我们调用函数并传递一组参数:
hello('Roger', 8)
形参通过引用传递。Python中的所有内容都是对象,但其中一些是不可变的,包括整数、布尔值、浮点数、字符串和元组。这意味着如果您将它们作为参数传递给函数,并在函数内部修改它们的值,则新值不会反映在函数外部:
def change(value):
value = 2
val = 1
change(val)
print(val) # 1
如果您传递一个可变的对象,并且(在函数内部)更改了它的一个属性,则该更改将反映在外部。
函数可以使用return
语句返回一个值。例如我们返回 name
参数:
def hello(name):
print('Hello ' + name + '!')
return name
当函数执行到return
语句时,该函数结束。
我们可以省略该返回值:
def hello(name):
print('Hello ' + name + '!')
return
我们可以在条件中包含return语句,这是在不满足起始条件时结束函数的常用方法:
def hello(name):
if not name:
return
print('Hello ' + name + '!')
如果我们调用该函数并传递一个计算结果为False
的表达式,比如一个空字符串,函数在到达print()
语句之前终止。
您可以使用逗号分隔来返回多个值:
def hello(name):
print('Hello ' + name + '!')
return name, 'Roger', 8
在这种情况下,调用 hello('Syd')
返回值是一个包含这 3 个值的元组:('Syd', 'Roger', 8)
。
Python中的一切都是对象。
原始类型(整数、字符串、浮点数……)的值也是对象。同时列表、元组、字典和一切也都是对象。
对象具有可以使用点语法访问的属性和方法。
例如,尝试定义一个int
类型的新变量:
age = 8
age
现在可以访问为int
对象定义的属性和方法。
这包括访问该数字的实部和虚部,例如:
rint(age.real) # 8
print(age.imag) # 0
print(age.bit_length()) # 4
# bit_length()方法返回该数字的二进制表示法所需的位数
列表类型的变量可以使用一组方法:
items = [1, 2]
items.append(3)
items.pop()
这些(可使用的)方法取决于变量的数据类型。
Python提供的全局函数id()
可让您检查特定对象在内存中的位置。
id(age) # 140170065725376
您(电脑上查看的age)的内存地址值会不一样——这里只是作为一个例子来展示。
如果给变量赋不同的值,它的地址会改变,因为变量已经指向存储在内存中另一个位置的另一个值:
ge = 8
print(id(age)) # 140535918671808
age = 9
print(id(age)) # 140535918671840
但是,如果您使用对象的方法修改该对象,其内存地址将保持不变:
items = [1, 2]
print(id(items)) # 140093713593920
items.append(3)
print(items) # [1, 2, 3]
print(id(items)) # 140093713593920
仅当您将变量重新赋一个值时,地址才会更改。
一些类型的对象是_可变的_,而另一些是_不可变的_。这取决于对象本身。
如果对象提供改变其内容的方法,那么它是可变的。否则它是不可变的。
Python定义的大多数类型都是不可变的, 例如int
,没有任何方法可以改变它的值。如果您增加它的值,
age = 8
age = age + 1
# 或者
age += 1
然后您使用id(age)
检查,您会发现age
前后指向不同的内存位置。原来的值并没有发生改变,age只是指向另一个值。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8