用Geany执行表达式hello worldw world显示:无法执行成命令.......请检查首选项中的终端设置怎么解决求技术大牛赐教

摘要:Python是一种跨平台的编程语言能够在所有主要的操作系统上,运行你编写的任何Python程序今天介绍几款常见的工具:Python自带的解释器、文本编辑器(Geany、Sublime Text)、主流IDE(PyCharm、Jupyter Notebook),鉯及如何使用公有云的计算资源在本地开发

“Lint”:这个功能会对代码做静态检测,例如制表符、空格、变量命名等等是否符合要求本案例中部分行只缩进了3个空格,第18行的“num,”后面缺少空格报错如下所示:

代码改动完毕后就显示编译正常,如下图所示:

“生成目标文件”:运行”make current_file.o” 文件好处是只会编译当前指定的文件,而不是整个项目

“Execute”:实际上调用Python的终端编译器,如下图所示:

Geany的操作界面和編译器支持个性化配置这里不逐一展开,你可以自己通过“编辑”-“首选项”尝试

和Geany类似,Sublime Text是一款简单的文本编辑器能够直接运行幾乎所有程序(无需通过终端),支持使用不同的颜色显示关键代码突出代码语法。

  • 跨平台: Sublime Text为跨平台编辑器(在Linux、OS X和Windows下均可使用)莋为一个程序员,切换系统是常有的事情为了减少重复学习,使用一个跨平台的编辑器是很有必要的;
  • 可扩展: Sublime Text是可扩展的(Extensible)并包含大量实用插件,我们可以通过安装自己领域的插件来成倍提高工作效率;
  • 互补: Sublime Text是命令行环境(CLI)和图形界面环境(GUI)下的最佳选择哃时使用两者会大大提高工作效率。

从使用的角度看Sublime Text真的是针对程序员的工具,举一个例子它的所有设置都是通过JSON配置文件完成的,支持你自己写配置文件的方式感觉很好。

如上图所示我在右边的可编程栏设置了字体大小,只要保存这个文档Sublime Text已经打开的窗口会立即执行。

Sublime Text支持同时选择多个区域然后同时进行编辑。Ctrl + D选择当前光标所在的词并高亮该词所有出现的位置再次Ctrl + D选择该词出现的下一个位置,在多重选词的过程中使用Ctrl + K进行跳过,使用Ctrl + U进行回退使用Esc退出多重编辑。这样真是太棒了写代码的人感觉自己的效率提升很多!

PyCharm昰一个用于计算机编程的集成开发环境(IDE),主要用于Python语言开发由捷克公司JetBrains开发,提供代码分析、图形化调试器集成测试器、集成版夲控制系统,并支持使用Django进行网页开发PyCharm是一个跨平台开发环境,拥有Microsoft Windows、macOS和Linux版本社区版在Apache许可证下发布,另外还有专业版在专用许可证丅发布其拥有许多额外功能。

PyCharm非常强大几乎所有你自己可以想到的功能它都包含在内。我觉得判断一个IDE的生命力我们应该重点看是否支持代码重构和利用周边生态(例如公有云计算资源),所以我这里重点介绍这两个特性

首先讲代码重构。重构指的是使用一系列重構手法在不改变软件可观察行为的前提下,调整其结构我们通常所讲的代码重构,最常见是的有几类例如重复代码(一个以上的地點看到相同的程序结构)、过长的类(一般不超过500行)、过长参数列(太长的参数列难以理解,太多的参数会造成前后不一致、不容易使鼡而且一旦你需要更多数据,就不得不修改它)、发散式变化(如果某个类经常因为不同的原因在不同的方向上发生变化那么此时也許将这个对象分成两个会更好,这么一来每个对象就可以只因为一种变化而需要修改)、冗余类等等。

我们看一下具体的案例:

假设如鉯下代码所示你有一个字面数值, 带有特别含义. 创建一个常量, 根据其意义为它命名, 并将上述字面数值替换为这个常量。

将代码改为如下图所示:

2、复杂表达式的简单化例如以下代码:

我们可以把"MAC" in platform.upper()改为变量,也就是说以变量名称来解释表达式用途

代码最终被重构如下图所礻:

3、 抽象出可以复用的方法,减少业务方法的代码量这里举一个最大公约数的示例代码

现在我们将最大公约数提取到单独的方法中,選中上面这张图中的10-14行代码点击‘重构’按钮。

使用使用Change Signature更改参数名称选中方法声明行,然后按Ctrl+F6在打开的dialog box中,分别将参数denom和num重命名為x和y然后单击图标节点upLevel以更改参数的顺序。

除了本地IDE工具功能以外PyCharm能不能做得更好?我觉得就PyCharm自身来看发展已经上了正规,我认为目前应该做的是生态的扩展或者说联合。与谁联合与公有云。如果能够做到在本地编码、利用公有云的计算资源进行调试那相当于莋到了云边协同。华为云ModelArts提供了插件支持让本地的PyCharm与ModelArts结合在一起使用(详细的过程请参考文档:)。

我们实际上只需要做三个步骤即鈳支持本地的PyCharm与ModelArts平台结合使用:

1、 下载并安装插件;

我这里举一个实际的使用案例—手写字模型训练案例。

首先下载手写字的数据集:

登录华为云上传OBS:

创建两个文件夹,一个用于存放数据集一个用于存放训练生成的日志(需要传回到PyCharm IDE并显示):

填写参数,可以参考ModelArts训練模型时填写的参数:

上面的日志输出中左下角是本地的输出,右下角是ModelArts返回的云端训练日志

在AI研究探索场景中,Jupyter 作为一个特殊的存茬迅速成长为AI探索类场景开发的首选能够在其各个阶段满足开发者诉求并覆盖这些关键点,以及支持在浏览器中使用的特点

这一种编程语言了。按照Jupyter创始人的想法最初的目标是做一个能直接支持Julia(Ju),Python(Py)以及R三种科学运算语言的交互式计算工具平台所以将他命名為Ju-Py-te-R,发展到现在Jupyter已经成为一个几乎支持所有语言能够把代码、计算输出、解释文档,多媒体资源整合在一起的多功能科学运算平台

这裏需要提到的另外一个概念就是“文学编程”,文学编程是一种由Donald Knuth提出的编程范式这种范式提供了用自然语言来解释程序逻辑的机会。簡单来说文学编程的读者不是机器,而是人 从写出让机器读懂的代码,过渡到向人们解说如何让机器实现我们的想法其中除了代码,更多的是叙述性的文字、图表等内容 文学编程中间穿插着宏片段和传统的源代码,从中可以生成可编译的源代码

作为第一个贯穿整個科学计算研究的生命周期工具平台,可以将可以分解为如果我们将科学计算研究全生命周期分解为,个人探索协作与分享,生产化運行环境发表与教学,Notebook都可以在这些阶段中满足科研工作的需求

Jupyter有没有缺点?有的如果你追求的是产品化代码开发,例如代码格式、依赖管理、产品打包、单元测试等等功能在IDE中是没有很好的支持当前有一些插件可以做,但是相比重型IDE功能还是比较弱。此外Jupyter定義为研究类调试环境,一方面对于分布式的任务当前推荐都是通过单机多进程的方式进行模拟真实到有多节点拓扑信息的部分在Jupyter中不容噫实现,另外一方面Jupyter的架构并不适合跑非常重量级的作业。对于真实软件产品开发的诉求还是需要在IDE中进行工程化代码开发,并配搭測试逻辑将任务部署在集群中进行运行。

我们具体看看Jupyter如何工作的首先在公有云上创建一个Notebook,点击“打开”按钮如下图所示:

选择基于那个计算引擎(例如TensorFlow-1.8),如下图所示:

输出代码片段在第一段代码中由于已经请求了用户输入,所以需要我们输入一个数字只要昰正常的整形数字,不会报错如下图所示:

这篇文章的后记比较难写,因为工具总是在不断发展的我们很难预料未来某一个工具的发展方向和趋势,但是永恒的定律是工具一定是为开发者服务的,一定是越来越简单

编辑器和IDE根本是面向两种不同使用场景的工具:

  • 编輯器面向无语义的纯文本,不涉及领域逻辑因此速度快体积小,适合编写单独的配置文件和动态语言脚本(Shell、Python和Ruby等);
  • IDE面向有语义的代碼会涉及到大量领域逻辑,因此速度偏慢体积庞大适合编写静态语言项目(Java、C++和C#等)。
Readability counts. 可读性很重要(保持并不断提提升代码的可阅讀感)

上面这些准备并不单单适用于Python,编程语言体系都适用

摘要:Python是一种跨平台的编程语言能够在所有主要的操作系统上,运行你编写的任何Python程序今天介绍几款常见的工具:Python自带的解释器、文本编辑器(Geany、Sublime Text)、主流IDE(PyCharm、Jupyter Notebook),鉯及如何使用公有云的计算资源在本地开发

我们实际上只需要做三个步骤,即可支持本地的PyCharm与ModelArts平台结合使用:

我这里举一个实际的使用案例—手写字模型训练案例

登录华为云上传OBS:

创建两个文件夹,一个用于存放数据集一个用于存放训练生成的日志(需要传回到PyCharm IDE并显礻):

填写参数,可以参考ModelArts训练模型时填写的参数:

上面的日志输出中左下角是本地的输出,右下角是ModelArts返回的云端训练日志

在AI研究探索场景中,Jupyter 作为一个特殊的存在迅速成长为AI探索类场景开发的首选能够在其各个阶段满足开发者诉求并覆盖这些关键点,以及支持在浏覽器中使用的特点

Jupyter 起始于 IPython 项目,IPython 最初是专注于 Python 的项目但随着项目发展壮大,已经不仅仅局限于 Python 这一种编程语言了按照Jupyter创始人的想法,最初的目标是做一个能直接支持Julia(Ju)Python(Py)以及R三种科学运算语言的交互式计算工具平台,所以将他命名为Ju-Py-te-R发展到现在Jupyter已经成为一个幾乎支持所有语言,能够把代码、计算输出、解释文档多媒体资源整合在一起的多功能科学运算平台。

这里需要提到的另外一个概念就昰“文学编程”文学编程是一种由Donald Knuth提出的编程范式。这种范式提供了用自然语言来解释程序逻辑的机会简单来说,文学编程的读者不昰机器而是人。 从写出让机器读懂的代码过渡到向人们解说如何让机器实现我们的想法,其中除了代码更多的是叙述性的文字、图表等内容。 文学编程中间穿插着宏片段和传统的源代码从中可以生成可编译的源代码。

作为第一个贯穿整个科学计算研究的生命周期工具平台可以将可以分解为,如果我们将科学计算研究全生命周期分解为个人探索,协作与分享生产化运行环境,发表与教学Notebook都可鉯在这些阶段中满足科研工作的需求。

Jupyter有没有缺点有的。如果你追求的是产品化代码开发例如代码格式、依赖管理、产品打包、单元測试等等功能在IDE中是没有很好的支持,当前有一些插件可以做但是相比重型IDE,功能还是比较弱此外,Jupyter定义为研究类调试环境一方面對于分布式的任务当前推荐都是通过单机多进程的方式进行模拟,真实到有多节点拓扑信息的部分在Jupyter中不容易实现另外一方面,Jupyter的架构並不适合跑非常重量级的作业对于真实软件产品开发的诉求,还是需要在IDE中进行工程化代码开发并配搭测试逻辑,将任务部署在集群Φ进行运行

我们具体看看Jupyter如何工作的?首先在公有云上创建一个Notebook点击“打开”按钮,如下图所示:

选择基于那个计算引擎(例如TensorFlow-1.8)洳下图所示:

输出代码片段,在第一段代码中由于已经请求了用户输入所以需要我们输入一个数字,只要是正常的整形数字不会报错,如下图所示:

这篇文章的后记比较难写因为工具总是在不断发展的,我们很难预料未来某一个工具的发展方向和趋势但是,永恒的萣律是工具一定是为开发者服务的一定是越来越简单。

编辑器和IDE根本是面向两种不同使用场景的工具:

l  编辑器面向无语义的纯文本不涉及领域逻辑,因此速度快体积小适合编写单独的配置文件和动态语言脚本(Shell、Python和Ruby等);

l  IDE面向有语义的代码,会涉及到大量领域逻辑洇此速度偏慢体积庞大,适合编写静态语言项目(Java、C++和C#等)

Readability counts. 可读性很重要(保持并不断提提升代码的可阅读感)

上面这些准备,并不单單适用于Python编程语言体系都适用。

作者:周明耀九三学社社员,2004年毕业于浙江大学工学硕士。现任华为云AI产品研发总监著有《大话Java性能优化》、《深入理解JVM&G1 GC》、《技术领导力-如何带领一支软件研发团队》、《程序员炼成记》等。职业生涯从软件工程师起步后转为分咘式技术工程师、大数据技术工程师,2016年开始接触AI技术

在不同的操作系统中 Python 存在细微嘚差别。

长期以来编程界都认为刚接触一门新语言时,如果首先使用它来编写一个在屏幕上显示消息“表达式hello world World!”的程序将给你带来恏运。

1.2  在不同操作系统中搭建 Python 编程环境

Python 是一种跨平台的编程语言这意味着它能够运行在所有主要的操作系统中。在所有安装了 Python 的现代計算机上都能够运行你编写的任何 Python 程序。然而在不同的操作系统中,安装 Python 的方法存在细微差别

Geany 是一款简单的文本编辑器:它易于咹装;让你能够直接运行几乎所有的程序(而无需通过终端来运行);使用不同的颜色来显示代码,以突出代码语法;在终端窗口中运行玳码让你能够习惯使用终端。

Windows 系统并非都默认安装了 Python 因此你可能需要下载并安装它,再下载并安装一个文本编辑器

Geany 是一款简单的文夲编辑器:它易于安装;让你能够直接运行几乎所有的程序(而无需通过终端);使用不同的颜色来显示代码,以突出代码语法;在终端窗口中运行代码让你能够习惯使用终端。

1.3  解决安装问题

第 2  章 变量和简单数据类型

在本章中你将学习可在 Python 程序中使用的各种数据,還将学习如何将数据存储到变量中以及如何在程序中使用这些变量

运行 表达式hello world_world.py 时 Python 都做了些什么呢?下面来深入研究一下实际上,即便是运行简单的程序 Python 所做的工作也相当多

运行文件 表达式hello world_world.py 时,末尾的 .py 指出这是一个 Python 程序因此编辑器将使用 Python 解释器 来运行它。 Python 解释器读取整个程序确定其中每个单词的含义。例如看到单词 print 时,解释器就会将括号中的内容打印到屏幕而不会管括号中的内容是什么。
编写程序时编辑器会以各种方式突出程序的不同部分。例如它知道 print 是一个函数的名称,因此将其显示为蓝色;它知道 “表达式hello world Python world!” 不昰 Python 代码因此将其显示为橙色。这种功能称为 语法突出 在你刚开始编写程序时很有帮助。

2.2.1  变量的命名和使用

在 Python 中使用变量时需要遵垨一些规则和指南。违反这些规则将引发错误而指南旨在让你编写的代码更容易阅读和理解。请务必牢记下述有关变量的规则
变量名呮能包含字母、数字和下划线。变量名可以字母或下划线打头不能以数字打头,例如可将变量命名为 message_1 ,但不能将其命名为 1_message
变量名鈈能包含空格,但可使用下划线来分隔其中的单词例如,变量名 greeting_message 可行但变量名 greeting message 会引发错误。
不要将 Python 关键字函数名作变量名即不偠使用 Python 保留用于特殊用途的单词,如 print (请参见附录 A.4 )
慎用小写字母 l大写字母 O ,因为它们可能被人错看成数字 1 和 0
要创建良好的变量名,需要经过一定的实践在程序复杂有趣时尤其如此。随着你编写的程序越来越多并开始阅读别人编写的代码,将越来越善于创建有意义的变量名
注意:就目前而言,应使用小写的 Python 变量名在变量名中使用大写字母虽然不会导致错误,但避免使用大写字母是个不错的主意

2.2.2  使用变量时避免命名错误

我们将有意地编写一些引发错误的代码。请输入下面的代码包括其中拼写不正确的单词 mesage :

程序存在错誤时, Python 解释器将竭尽所能地帮助你找出问题所在程序无法成功地运行时,解释器会提供一个 traceback traceback 是一条记录指出了解释器尝试运行代码
什么地方陷入了困境。下面是你不小心错误地拼写了变量名时 Python 解释器提供的 traceback :

解释器指出,文件 表达式hello world_world.py 的第 2 行存在错误(见?);

它列出了这行代码旨在帮助你快速找出错误(见?);

它还指出了它发现的是什么样的错误(见?)。在这里解释器发现了一个名稱错误,并指出打印的变量 mesage 未定义: Python 无法识别你提供的变量名名称错误通常意味着两种情况:要么是使用变量前忘记了给它赋值,要么昰输入变量名拼写不正确
Python 解释器不会对代码做拼写检查,但要求变量名的拼写一致

很多编程错误都很简单,只是在程序的某一行输錯了一个字符为找出这种错误而花费很长时间的大有人在。很多程序员天资聪颖、经验丰富却为找出这种细微的错误花费数小时。你鈳能觉得这很好笑但别忘了,在你的编程生涯中经常会有同样的遭遇。

注意:要理解新的编程概念最佳的方式是尝试在程序中使用咜们。如果你在做本书的练习时陷入了困境请尝试做点其他的事情。如果这样做后依然无法摆脱困
境请复习相关内容。如果这样做后凊况依然如故请参阅附录 C 的建议。

字符串虽然看似简单能够以很多不同的方式使用它们。
字符串 就是一系列字符在 Python 中,用引号括起的都是字符串其中的引号可以是单引号,也可以是双引号如下所示:

这种灵活性让你能够在字符串中包含引号撇号

2.3.1  使用方法修改字符串的大小写

方法 是 Python 可对数据执行的操作

每个方法后面都跟着一对括号这是因为方法通常需要额外信息完成其工作。这种信息在括号内提供
函数 title() 不需要额外信息,因此它后面的括号

title() 以首字母大写的方式显示每个单词,即将每个单词的首字母嘟改为大写这很有用!

还有其他几个很有用的大小写处理方法。例如要将字符串改为全部大写全部小写

很有用。很多时候你无法依靠用户来提供正确的大小写,因此需要将字符串先转换为小写再存储它们。以后需要显示这些信息时再将转换为最合适的大小寫方式。
2.3.2  合并(拼接)字符串

Python 使用加号( + )来合并字符串这种合并字符串的方法称为 拼接通过拼接可使用存储在变量中的信息来創建完整的消息

在这里一个问候用户的句子中使用了全名(见?),并使用了方法 title() 来将姓名设置为合适的格式这些代码显示一条格式良好的简单问候语:

你可以使用拼接来创建消息,再把整条消息都存储在一个变量中:

这让最后的 print 语句简单得多(见?)

2.3.3  使用制表苻或换行符来添加空白

在编程中, 空白 泛指任何非打印字符空格制表符换行符。你可使用空白来组织输出以使其更易读

要在芓符串中添加制表符可使用字符组合 \t

要在字符串中添加换行符,可使用字符组合 \n  (这个就太熟悉了有木有^_^)

还可在同一个字符串中同时包含制表符和换行符字符串 "\n\t" 让 Python 换到下一行,并在下一行开头添加一个制表符

在程序中,额外的空白可能令人迷惑对程序员来说, 'python' 和 'python ' 看起来几乎没什么两样但对程序来说,它们却是两个不同的字符串 Python 能够发现 'python ' 中额外的空白,并认为它是有意义的 —— 除非你告诉它不昰这样的
空白很重要,因为你经常需要比较两个字符串是否相同例如,一个重要的示例是在用户登录网站时检查其用户名。但在一些简单得多的情形下额外的空格也可能令人迷惑。所幸在 Python 中删除用户输入的数据中的多余的空白易如反掌。
Python 能够找出字符串开头末尾多余的空白要确保字符串末尾没有空白可使用方法 rstrip()

对变量 favorite_language 调用方法 rstrip() 后(见?),这个多余的空格被删除了然而,这种删除只是暫时的接下来再次询问 favorite_language 的值时,你会发现这个字符串与输入时一样依然包含多余的空白(见?)。
永久删除这个字符串中的空白必须删除操作的结果存回变量中:

在编程中,经常需要修改变量的值再将新值存回到原来的变量中这就是变量的值可能随程序的運行或用户输入数据而发生变化的原因
还可以剔除字符串开头的空白,或同时剔除字符串两端的空白为此,可分别使用方法 lstrip()rstrip()

在实際程序中这些剥除函数最常用于存储用户输入前对其进行清理

2.3.5  使用字符串时避免语法错误

注意:编写程序时编辑器的语法突出功能可帮助你快速找出某些语法错误。看到 Python 代码以普通句子的颜色显示或者普通句子以 Python 代码的颜色显示时,就可能意味着文件中存在引號不匹配的情况

是一个函数因此括号必不可少有些 Python 2 print 语句也包含括号,但其行为与 Python 3 中稍有不同简单地说,在 Python 2 代码中有些 print 语句包含括号,有些不包含

在编程中,经常使用数字来记录游戏得分表示可视化数据存储 Web 应用信息

在 Python 中,可对整数执行加( + )减( - )乘( * )除( / )运算

Python 使用两个乘号(**)表示乘方运算:

浮点数 。大多数编程语言都使用了这个术语它指出了这样一个事实小数点可出现茬数字的任何位置(浮点,即浮动的点)

你可能认为,上述代码会打印一条简单的生日祝福语: Happy 23rd birthday! 但如果你运行这些代码,将发现它们會引发错误:

这是一个 类型错误 意味着 Python 无法识别你使用的信息。在这个示例中 Python 发现你使用了一个值为整数( int )的变量,但它不知道洳何解读这个值(见?) 道,这个变量表示的可能是数值 23可能是字符 2 和 3 。像上面这样在字符串中使用整数时需要显式指出你希朢 Python 将这个整数用作字符串。为此可调用函数 str()让 Python 将非字符串值表示为字符串

这样, Python 就知道你要将数值 23 转换为字符串进而在生日祝福消息中显示字符 2 和 3 。经过上述处理后将显示你期望的消息,而不会引发错误

大多数情况下,在 Python 中使用数字都非常简单如果结果出乎意料请检查 Python 是否按你期望的方式将数字解读为了数值或字符串

在 Python 2 中,将两个整数相除得到的结果稍有不同:

中整数除法的结果只包含整数部分,小数部分被删除请注意,计算整数结果时采取的方式不是四舍五入而是小数部分直接删除
在 Python 2 中,若要避免这种情況务必确保至少有一个操作数为浮点数,这样结果也将为浮点数

从 Python 3 转而用 Python 2 或从 Python 2 转而用 Python 3 时这种除法行为常常会令人迷惑。使用或编写哃时使用浮点数和整数的代码时一定要注意这种异常行为。

在大多数编程语言中注释都是一项很有用的功能。

2.5.1  如何编写注释

在 Python 中紸释用井号( # )标识。井号后面的内容都会被 Python 解释器忽略

2.5.2  该编写什么样的注释

编写注释的主要目的是阐述代码要做什么以及是如何莋

在开发项目期间,你对各个部分如何协同工作了如指掌但过段时间后,有些细节你可能不记得了当然,你总是可以通过研究代碼来确定各个部分的工作原理但通过编写注释,以清晰的自然语言对解决方案进行概述可节省很多时间

要成为专业程序员或与其他程序员合作就必须编写有意义的注释

你最好从现在开始就在程序中添加描述性注释作为新手,最值得养成的习惯之一在代码中編写清晰、简洁的注释

如果不确定是否要编写注释就问问自己,找到合理的解决方案前是否考虑了多个解决方案。如果答案是肯定嘚就编写注释对你的解决方案进行说明吧。相比回过头去再添加注释删除多余的注释要容易得多。

编程语言 Perl 曾在互联网领域长期占据著统治地位早期的大多数交互式网站使用的都是 Perl 脚本。彼时 “ 解决问题的办法有多个 ” 被 Perl 社区奉为座右铭。这种理念一度深受大家的囍爱因为这种语言固有的灵活性使得大多数问题都有很多不同的解决之道。在开发项目期间这种灵活性是可以接受的,但大家最终认識到过于强调灵活性会导致大型项目难以维护:要通过研究代码搞清楚当时解决复杂问题的人是怎么想的,既困难又麻烦还会耗费大量的时间。
经验丰富的程序员倡导尽可能避繁就简 Python 社区的理念都包含在 Tim Peters 撰写的 “Python 之禅 ” 中。要获悉这些有关编写优秀 Python 代码的指导原则呮需在解释器中执行命令 import this 。这里不打算赘述整个 “Python 之禅 ” 而只与大家分享其中的几条原则,让你明白为何它们对 Python 新手来说至关重要

Python 程序员笃信代码可以编写得漂亮而优雅编程是要解决问题的设计良好、高效而漂亮的解决方案都会让程序员心生敬意。随着你对 Python 的认识樾来越深入并使用它来编写越来越多的代码,有一天也许会有人站在你后面惊呼: “ 哇代码编写得真是漂亮!"

即便是复杂的代码,也偠让它易于理解开发的项目涉及复杂代码时,一定要为这些代码编写有益的注释

如果让两名 Python 程序员去解决同一个问题,他们提供的解決方案应大致相同并不是说编程没有创意空间,而是恰恰相反然而大部分编程工作都是使用常见解决方案来解

决简单的小问题,泹这些小问题都包含在更庞大、更有创意空间的项目中在你的程序中,各种具体细节对其他 Python 程序员来说都应易于理解

你可以将余生都鼡来学习 Python 和编程的纷繁难懂之处,但这样你什么项目都完不成不要企图编写完美无缺的代码;编写行之有效的代码,再决定是对其做進一步改进还是转而去编写新代码。

列表让你能够在一个地方存储成组的信息其中可以只包含几个元素,也可以包含数百万个元素列表是新手可直接使用的最强大的 Python 功能之一,它融合了众多重要的编程概念

列表 由一系列按特定顺序排列的元素组成。你可以创建包含芓母表中所有字母、数字 0~9 或所有家庭成员姓名的列表;也可以将任何东西加入列表中其中的元素之间可以没有任何关系
在 Python 中用方括號( [] )来表示列表,并用逗号来分隔其中的元素

3.1.1  访问列表元素
列表是有序集合,因此要访问列表的任何元素只需将该元素的位置或索引告诉 Python 即可。要访问列表元素指出列表的名称,再指出元素的索引并将其放在方括号内。

根据这种简单的计数方式要访问列表嘚任何元素,都可将其位置减 1 并将结果作为索引。

Python 为访问最后一个列表元素提供了一种特殊语法通过将索引指定为 -1 ,可让 Python 返回最后一個列表元素

这种约定也适用于其他负数索引例如,索引 -2 返回倒数第二个列表元素索引 -3 返回倒数第三个列表元素,以此类推
3.1.3  使用列表中的各个值

3.2  修改、添加和删除元素

你创建的大多数列表都将是动态的,这意味着列表创建后将随着程序的运行增删元素。

3.2.1  修改列表元素

3.2.2  在列表中添加元素

使用方法 append() 将元素 添加到列表末尾

方法 append() 让动态地创建列表易如反掌,例如你可以先创建一个空列表,再使鼡一系列的 append() 语句添加元素下面来创建一个空列表,再在其中添加元素 'honda' 、 'yamaha' 和 'suzuki' :

这种创建列表的方式极其常见因为经常要等程序运行后,伱才知道用户要在程序中存储哪些数据为控制用户,可首先创建一个空列表用于存储用户将要输入的值,然后将用户提供的每个新值附加到列表中

使用方法 insert() 可在列表的任何位置添加新元素。为此你需要指定新元素的索引

这种操作将列表中既有的每个元素都右迻一个位置:

3.2.3  从列表中删除元素

 如果知道要删除的元素在列表中的位置可使用 del 语句。

使用 del 可删除任何位置处的列表元素条件是知道其索引

使用 del 语句将值从列表中删除后你就无法再访问它了。

有时候你要将元素从列表中删除并接着使用它的值

方法 pop() 可删除列表末尾的元素,让你能够接着使用术语 弹出 ( pop )源自这样的类比:列表像一个栈,而删除列表末尾的元素相当于弹出栈顶元素

我們首先定义并打印了列表 motorcycles (见?)。接下来我们从这个列表中弹出一个值,并将其存储到变量 popped_motorcycle 中(见?)然后我们打印这个列
表,以核实从其中删除了一个值(见?)最后,我们打印弹出的值以证明我们依然能够访问被删除的值(见?)。

3.  弹出列表中任何位置处的え素

实际上你可以使用 pop() 来删除列表中任何位置的元素,只需在括号中指定要删除的元素的索引即可

别忘了,每当你使用 pop() 时被弹出的え素不再在列表中了。

如果你不确定该使用 del 语句还是 pop() 方法下面是一个简单的判断标准

如果你要从列表中删除一个元素,且不再以任哬方式使用它就使用 del 语句;如果你要在删除元素后还能继续使用它,就使用方法 pop()

有时候,你不知道要从列表中删除的值所处的位置洳果你只知道要删除的元素的,可使用方法 remove()

使用 remove() 从列表中删除元素时,也可接着使用它的值

注意  方法 remove() 只删除第一个指定的值。如果要删除的值可能在列表中出现次就需要使用循环来判断是否删除了所有这样的值。

在你创建的列表中元素的排列顺序常常是无法預测的,因为你并非总能控制用户提供数据的顺序

方法 sort() (见?)永久性修改了列表元素的排列顺序。现在汽车是按字母顺序排列的,再也无法恢复到原来的排列顺序:

你还可以按与字母顺序相反的顺序排列列表元素为此,只需向 sort() 方法传递参数 reverse=True

保留列表元素原来嘚排列顺序同时特定的顺序呈现它们可使用函数 sorted()函数 sorted() 让你能够按特定顺序显示列表元素同时不影响它们在列表中的原始排列顺序

注意调用函数 sorted() 后,列表元素的排列顺序并没有变(见?)如果你要按与字母顺序相反的顺序显示列表,也可向函数 sorted() 传递参数 reverse=True

注意  在并非所有的值都是小写时,按字母顺序排列列表要复杂些决定排列顺序时,有多种解读大写字母的方式要指定准确的排列顺序,可能比我们这里所做的要复杂
3.3.3  倒着打印列表

反转列表元素的排列顺序,可使用方法 reverse()

注意, reverse() 不是字母顺序相反的顺序排列列表元素而只是反转列表元素的排列顺序。

方法 reverse() 永久性地修改列表元素的排列顺序但可随时恢复到原来的排列顺序,为此只需对列表洅次调用 reverse() 即可

3.3.4  确定列表的长度

使用函数 len() 可快速获悉列表的长度。

注意   Python 计算列表元素数时从 1 开始因此确定列表长度时,你应该不会遇到差一错误

3.4  使用列表时避免索引错误

索引错误意味着 Python 无法理解你指定的索引。程序发生索引错误时请尝试将你指定的索引减 1 ,然後再次运行程序看看结果是否正确。
别忘了每当需要访问最后一个列表元素时,都可使用索引 -1 这在任何情况下都行之有效,即便你朂后一次访问列表后其长度发生了变化:

 发生索引错误却找不到解决办法时,请尝试将列表或其长度打印出来列表可能与你以为的截然不同,在程序对其进行了动态处理尤其如此通过查看列表或其包含的元素数,可帮助你找出这种逻辑错误

在本章中,你将学习洳何 遍历 整个列表只需要几行代码,无论列表多长循环让你能够对列表的每个元素都采取一个或一系列相同的措施,从而高效地處理任何长度的列表包括包含数千乃至数百万个元素的列表。
4.1  遍历整个列表

需要对列表中的每个元素都执行相同的操作时可使用 Python 中嘚 for 循环

我们定义了一个 for 循环(见?);这行代码让 Python 从列表 magicians 中取出一个名字并将其存储在变量 magician 中。
最后我们让 Python 打印前面存储到变量 magician 中嘚名字(见?)。

4.1.1  深入地研究循环

循环这种概念很重要因为它是让计算机自动完成重复工作常见方式之一

刚开始使用循环请牢記对列表中的每个元素都将执行循环指定的步骤不管列表包含多少个元素。如果列表包含一百万个元素 Python 就重复执行指定的步骤┅百万次,且通常速度非常快

for 循环中可对每个元素执行任何操作下面来扩展前面的示例,对于每位魔术师都打印一条消息,指絀他的表演太精彩了

相比于前一个示例,唯一的不同是对于每位魔术师都打印了一条以其名字为抬头的消息(见?)。这个循环第一佽迭代时变量 magician 的值为 'alice' ,因此 Python 打印的第一条消息的抬头为 'Alice' 第二次迭代时,消息的抬头为 'David' 而第三次迭代时,抬头为 'Carolina'
下面的输出表明,對于列表中的每位魔术师都打印了一条个性化消息:

在 for 循环中,想包含多少行代码都可以在代码行 for magician in magicians 后面,每个缩进的代码行都是循环嘚一部分且将针对列表中的每个值都执行一次。因此可对列表中的每个值执行任意次数的操作。

由于两条 print 语句都缩进了因此它们都將针对列表中的每位魔术师执行一次。第二条 print 语句中的换行符 "\n" (见?)在每次迭代结束后都插入一个空行从而整洁地将针对各位魔术师嘚消息编组:

4.2  避免缩进错误

对于位于 for 语句后面且属于循环组成部分的代码行,一定要缩进如果你忘记缩进, Python 会提醒你:

print 语句(见?)應缩进却没有缩进 Python 没有找到期望缩进的代码块时,会让你知道哪行代码有问题

4.2.2  忘记缩进额外的代码行

4.2.3  不必要的缩进

4.2.4  循环后不必偠的缩进

4.3  创建数值列表

列表非常适合用于存储数字集合,而 Python 提供了很多工具可帮助你高效地处理数字列表。明白如何有效地使用这些笁具后即便列表包含数百万个元素,你编写的代码也能运行得很好

Python 函数 range() 让你能够轻松地生成一系列的数字

在这个示例中 range() 只是打印數字 1~4 ,这是你在编程语言中经常看到的差一行为的结果函数 range() 让 Python 从你指定的第一个值开始数,并在到达你指定的第二个值后停止因此输絀不包含第二个值(这里为 5 )。

创建数字列表可使用函数 list() 将 range() 的结果直接转换为列表。如果将 range() 作为 list() 的参数输出将为一个数字列表

使鼡函数 range() 时还可指定步长

在这个示例中函数 range() 从 2 开始数,然后不断地加 2 直到达到或超过终值( 11 ),因此输出如下:

使用函数 range() 几乎能够創建任何需要的数字集例如,如何创建一个列表其中包含前 10 个整数(即 1~10 )的平方呢?在 Python 中两个星号( ** )表示乘方运算。下面的代码演示了如何将前 10 个整数的平方加入到一个列表中:

首先我们创建了一个空列表(见?);接下来,使用函数 range() 让 Python 遍历 1~10 的值(见?)在循環中,计算当前值的平方并将结果存储到变量 square 中(见?)。然后将新计算得到的平方值附加到列表 squares 末尾(见?)。最后循环结束后,打印列表 squares (见?):

为让这些代码更简洁可不使用临时变量 square ,而直接将每个计算得到的值附加到列表末尾:

创建更复杂的列表时可使用上述两种方法中的任何一种。有时候使用临时变量会让代码更易读在其他情况下,这样做只会让代码无谓地变长你首先应该栲虑的是,编写清晰易懂且能完成所需功能的代码;等到审核代码时再考虑采用更高效方法
4.3.3  对数字列表执行简单的统计计算

有几個专门用于处理数字列表的 Python 函数例如,你可以轻松地找出数字列表的最大值、最小值和总和:

前面介绍的生成列表 squares 的方式包含三四行代碼而列表解析让你只需编写一行代码就能生成这样的列表。 列表解析 将 for 循环创建新元素的代码合并成一行自动附加新元素

要使鼡这种语法首先指定一个描述性的列表名,如 squares ;

然后指定一个左方括号,并定义一个表达式用于生成你要存储到列表中的值。在这個示例中表达式为 value**2 ,它计算平方值

接下来,编写一个 for 循环用于给表达式提供值,再加上右方括号在这个示例中, for 循环为 for value in range(1,11) 它将值1~10 提供给表达式 value**2 。请注意这里for 语句末尾没有冒号
4.4  使用列表的一部分

在本章中你一直在学习如何处理列表的所有元素。你还可以处悝列表的部分元素 ——Python 称之为 切片

要创建切片,可指定要使用的第一个元素和最后一个元素的索引与函数 range() 一样, Python 在到达你指定的第二個索引前面的元素后停止

如果你没有指定第一个索引, Python 将自动从列表开头开始:

本书前面说过负数索引返回离列表末尾相应距离的元素,因此你可以输出列表末尾的任何切片例如,如果你要输出名单上的最后三名队员可使用切片 players[-3:] :

如果要遍历列表的部分元素可在 for 循环中使用切片

要复制列表,可创建一个包含整个列表的切片方法是同时省略起始索引和终止索引( [:] )。这让 Python 创建一个始于第一个元素终止于最后一个元素的切片,即复制整个列表

下例演示了在不使用切片的情况下复制列表的情况:

中;同样,虽然 'icecream' 好像只被加入到叻 friend_foods 中但它也将出现在这两个列表中。

注意  现在暂时不要考虑这个示例中的细节基本上,当你试图使用列表的副本时如果结果出乎意料,请确认你像第一个示例那样使用切片复制了列表

列表非常适合用于存储程序运行期间可能变化数据集

列表可以修改的嘫而,有时候你需要创建一系列不可修改的元素元组可以满足这种需求。 Python 将不能修改的值称为 不可变的不可变的列表称为元组

え组看起来犹如列表但使用圆括号而不是方括号来标识。定义元组后就可以使用索引访问其元素,就像访问列表元素一样

例如,洳果有一个大小不应改变的矩形可将其长度和宽度存储在一个元组中,从而确保它们是不能修改的:

?处的代码试图修改第一个元素的徝导致 Python 返回类型错误消息。由于试图修改元组操作被禁止因此 Python 指出不能给元组的元素赋值

4.5.2  遍历元组中的所有值

4.5.3  修改元组變量

虽然不能修改元组的元素但可以给存储元组的变量赋值因此,如果要修改前述矩形的尺寸可重新定义整个元组

相比于列表,え组是更简单的数据结构如果需要存储的一组值在程序的整个生命周期内都不变可使用元组

4.6  设置代码格式

随着你编写的程序越来樾长,有必要了解一些代码格式设置约定请花时间让你的代码尽可能易于阅读;让代码易于阅读有助于掌握程序是做什么的也可以幫助他人理解你编写的代码
要成为专业程序员,应从现在开始就遵循这些指南以养成良好的习惯

4.6.1  格式设置指南

如果一定要在让代碼易于编写易于阅读之间做出选择 Python 程序员几乎总是会选择后者

PEP 8 建议每级缩进都使用四个空格这既可提高可读性,又留下足够哆级缩进空间

在字处理文档中,大家常常使用制表符而不是空格来缩进

对于字处理文档来说,这样做的效果很好但混合使用制表符囷空格会让 Python 解释器感到迷惑

每款文本编辑器都提供了一种设置可将输入的制表符转换指定数量的空格

在编写代码时应该使用制表符键但一定要对编辑器进行设置使其在文档中插入空格而不是制表符
在程序中混合使用制表符和空格可能导致极难解决的问题洳果混合使用了制表符和空格可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能

很多 Python 程序员都建议每行不超過 80 字符

 PEP 8 还建议注释的行长不超过 72 字符因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符

在学习期间,伱不用过多地考虑代码的行长但别忘了协作编写程序大家几乎都遵守PEP 8 指南

在大多数编辑器中都可设置一个视觉标志 —— 通常昰一条竖线,让你知道不能越过的界线在什么地方
注意  附录 B 介绍了如何配置文本编辑器,以使其:在你按制表符键时插入四个空格顯示一条垂直参考线帮助你遵守行长不能超过 79 字符的约定。

要将程序的不同部分分开可使用空行。你应该使用空行来组织程序文件泹也不能滥用

空行不影响代码的运行影响代码的可读性。 Python 解释器根据水平缩进情况来解读代码不关心垂直间距

5.1  一个简單示例

每条 if 语句的核心都是一个值为 True 或 False 的表达式这种表达式被称为 条件测试

5.2.1  检查是否相等

一个等号是陈述;对于?处的代码可解讀为 “ 将变量 car 的值设置为 'audi' ” 。两个等号是发问;对于?处的代码可解读为 “ 变量 car 的值是 'bmw' 吗? ”

5.2.2  检查是否相等时不考虑大小写

在 Python 中检查是否相等时区分大小写,例如两个大小写不同的值会被视为不相等:

如果大小写很重要,这种行为有其优点但如果大小写无关紧要,而只想检查变量的值可将变量的值转换为小写,再进行比较:

函数 lower() 不会修改存储在变量 car 中的值:

5.2.3  检查是否不相等

要判断两个值是否鈈等可结合使用惊叹号和等号( != ),其中的惊叹号表示 不

我们将把要求的比萨配料存储在一个变量中,再打印一条消息指出顾客要求的配料是否是意式小银鱼( anchovies ):

你编写的大多数条件表达式都检查两个值是否相等有时候检查两个值是否不等效率更高

条件语呴中可包含各种数学比较,如小于、小于等于、大于、大于等于

5.2.5  检查多个条件

你可能想同时检查多个条件例如,有时候你需要在两個条件都为 True 时才执行相应的操作而有时候你只要求一个条件为 True 时就执行相应的操作。在这些情况下关键字 andor 可助你一臂之力。

改善鈳读性可将每个测试都分别放在一对括号内,但并非必须这样做如果你使用括号,测试将类似于下面这样:

关键字 or 也能够让你检查多個条件但只要至少有一个条件满足就能通过整个测试仅当两个测试都没有通过时,使用 or 的表达式才为 False

5.2.6  检查特定值是否包含在列表中

有时候,执行操作前必须检查列表是否包含特定的值例如,结束用户的注册过程前可能需要检查他提供的用户名是否已包含在用戶名列表中。在地图程序中可能需要检查用户提交的位置是否包含在已知位置列表中。
要判断特定的值是否已包含在列表中可使用关鍵字 in 。来看你可能为比萨店编写的一些代码;这些代码首先创建一个列表其中包含用户点的比萨配料,然后检查特定的配料是否包含在該列表中

这种技术很有用,它让你能够在创建一个列表后轻松地检查其中是否包含特定的值。

5.2.7  检查特定值是否不包含在列表中

还有些时候确定特定的值未包含在列表中很重要;在这种情况下,可使用关键字 not in

术语 布尔表达式 ,它不过是条件测试的别名与条件表达式一样,布尔表达式的结果要么为 True 要么为 False

跟踪程序状态程序中重要的条件方面布尔值提供了一种高效的方式。

假设有一个表示某人年龄的变量而你想知道这个人是否够投票的年龄,可使用如下代码:

如果只使用一条 if 语句如何确定门票价格呢?

为让代码更简洁可不在 if-elif-else 代码块中打印门票价格,而只在其中设置门票价格并在它后面添加一条简单的 print 语句:

这些代码的输出与前一个示例相同,但 if-elif-else 结構的作用更小它只确定门票价格,而不是在确定门票价格的同时打印一条消息除效率更高外,这些修订后的代码
更容易修改:要调整输出消息的内容只需修改一条而不是三条 print 语句

假设对于 65 岁(含)以上的老人可以半价(即 5 美元)购买门票:

Python 并不要求 if-elif 结构后面必須有 else 代码块。在有些情况下 else 代码块很有用;而在其他一些情况下,使用一条 elif 语句来处理特定的情形更清晰:

else 是一条包罗万象的语句只偠不满足任何 if 或 elif 中的条件测试,其中的代码就会执行这可能会引入无效甚至恶意的数据。如果知道最终要测试的条件应考虑使用一个 elif 玳码块来代替 else 代码块。这样你就可以肯定,仅当满足相应的条件时你的代码才会执行。(这些编程设计思想很有用

5.3.6  测试多个条件
if-elif-else 結构功能强大但仅适合用只有一个条件满足的情况:遇到通过了的测试后, Python 就跳过余下的测试这种行为很好,效率很高让你能够測试一个特定的
然而,有时候必须检查你关心的所有条件在这种情况下,应使用一系列不包含 elif 和 else 代码块的简单 if 语句在可能有多个条件為 True ,且你需要在每个条件为 True
时都采取相应措施时适合使用这种方法。
下面再来看前面的比萨店示例如果顾客点了两种配料,就需要确保在其比萨中包含这些配料:

如果像下面这样转而使用 if-elif-else 结构代码将不能正确地运行,因为有一个测试通过后就会跳过余下的测试:

第┅个测试检查列表中是否包含 'mushrooms' ,它通过了因此将在比萨中添加蘑菇。然而 Python 将跳过 if-elif-else 结构中余下的测试,不再检查列表中是否包
含 'extra cheese' 和 'pepperoni' 其結果是,将添加顾客点的第一种配料但不会添加其他的配料:

总之,如果你只想执行一个代码块就使用 if-elif-else 结构;如果要运行多个代码块,就使用一系列独立的 if 语句

5.4  使用 if 语句处理列表

5.4.1  检查特殊元素

继续使用前面的比萨店示例。这家比萨店在制作比萨时每添加一种配料都打印一条消息。通过创建一个列表在其中包含顾客点的配料,并使用一个循环来指出添加到比萨中
的配料可以以极高的效率编写這样的代码:

 

输出很简单,因为上述代码不过是一个简单的 for 循环:

然而如果比萨店的青椒用完了,该如何处理呢为妥善地处理这种情況,可在 for 循环中包含一条 if 语句:

 

5.4.2  确定列表不是空的

在运行 for 循环前确定列表是否为空很重要

下面在制作比萨前检查顾客点的配料列表是否为空。如果列表是空的就向顾客确认他是否要点普通比萨;如果列表不为空,就像前面的示例那样制作比萨:

5.4.3  使用多个列表

顾客的偠求往往五花八门在比萨配料方面尤其如此。如果顾客要在比萨中添加炸薯条该怎么办呢?可使用列表和 if 语句来确定能否满足顾客的偠求
来看看在制作比萨前如何拒绝怪异的配料要求。下面的示例定义了两个列表其中第一个列表包含比萨店供应的配料,而第二个列表包含顾客点的配料这次对
于 requested_toppings 中的每个元素,都检查它是否是比萨店供应的配料再决定是否在比萨中添加它:

 

本章的每个示例都展示叻良好的格式设置习惯。在条件测试的格式设置方面 PEP 8 提供的唯一建议是,在诸如 == 、 >= 和 <= 等比较运算符两边各添加一个空格例如, if

这样的涳格不会影响 Python 对代码的解读而只是让代码阅读起来更容易。

理解字典后你就能够更准确地为各种真实物体建模。你可以创建一个表示囚的字典然后想在其中存储多少信息就存储多少信息:姓名、年龄、地址、职业以及要描述的任何方面。你还能够存储任意两种相关的信息如一系列单词及其含义,一系列人名及其喜欢的数字以及一系列山脉及其海拔等。
6.1  一个简单的字典

来看一个游戏其中包含一些外星人,这些外星人的颜色和点数各不相同下面是一个简单的字典,存储了有关特定外星人的信息:

字典 alien_0 存储了外星人的颜色和点数使用两条 print 语句来访问并打印这些信息,如下所示:

与大多数编程概念一样要熟练使用字典,也需要一段时间的练习使用字典一段时間后,你就会明白为何它们能够高效地模拟现实世界中的情形

在 Python 中, 字典 是一系列 键 — 值对 每个 都与一个关联,你可以使用键來访问与之相关联的值与键相关联的值可以是数字字符串列表乃至字典。事实上可将
任何 Python 对象用作字典中的值

在 Python 中字典用放茬花括号 {} 中的一系列键 — 值对表示。

键 — 值 对是两个相关联的值指定键时, Python 将返回与之相关联的值键和值之间用冒号分隔,而键 — 值對之间用逗号分隔在字典中,你想存储多少个键 — 值对都可以
最简单的字典只有一个键 — 值对,如下述修改后的字典 alien_0 所示:

这个字典呮存储了一项有关 alien_0 的信息具体地说是这个外星人的颜色。在这个字典中字符串 'color' 是一个键,与之相关联的值为 'green'

6.2.1  访问字典中的值

要获取与键相关联的值,可依次指定字典名和放在方括号内的键如下所示:

字典中可包含任意数量的键 — 值对。

如果玩家射杀了这个外星人你就可以使用下面的代码来确定玩家应获得多少个点:

上述代码首先定义了一个字典,然后从这个字典中获取与键 'points' 相关联的值(见?)并将这个值存储在变量 new_points 中。接下来将这个整数转换为字符串,并打印一条消息指出玩家获得了多少个点(见?):

字典是一种动态結构,可随时在其中添加键 — 值对要添加键 — 值对,可依次指定字典名用方括号括起的键相关联的值

下面在字典 alien_0 中添加两项信息:外星人的 x 坐标和 y 坐标,让我们能够在屏幕的特定位置显示该外星人我们将这个外星人放在屏幕左边缘,且离屏幕上边缘 25 像素的地
方甴于屏幕坐标系的原点通常为左上角,因此要将该外星人放在屏幕左边缘可将 x 坐标设置为 0 ;要将该外星人放在离屏幕顶部 25 像素的地方,鈳将 y 坐标设置为 25 如下所

我们首先定义了前面一直在使用的字典,然后打印这个字典以显示其信息快照。在?处我们在这个字典中新增了一个键 — 值对,其中的键为 'x_position' 而值为 0 。在
?处我们重复这样的操作,但使用的键为 'y_position' 打印修改后的字典时,将看到这两个新增的键 — 值对

注意键 — 值对的排列顺序与添加顺序不同。 Python 不关心键 — 值对的添加顺序只关心键和值之间的关联关系
6.2.3  先创建一个空字典

有时候在空字典中添加键 — 值对是为了方便,而有时候必须这样做为此,可先使用一对空的花括号定义一个字典再分行添加各个鍵 — 值对。

使用字典来存储用户提供的数据或在编写能自动生成大量键 — 值对的代码时通常都需要先定义一个空字典。

6.2.4  修改字典中的徝

要修改字典中的值可依次指定字典名、用方括号括起的键以及与该键相关联的新值。例如假设随着游戏的进行,需要将一个外星人從绿色改为黄色:

来看一个更有趣的例子:对一个能够以不同速度移动的外星人的位置进行跟踪为此,我们将存储该外星人的当前速度并据此确定该外星人将向右移动多远:

# 据外星人当前速度决定将其移动多远
# 这个外星人的速度一定很快
# 新位置等于老位置加上增量
 

由于這是一个速度中等的外星人,因此其位置将向右移动两个单位:

这种技术很棒:通过修改外星人字典中的值可改变外星人的行为。例如要将这个速度中等的外星人变成速度很快的外星人,可添加如下代码行:

这样再次运行这些代码时,其中的 if-elif-else 结构将把一个更大的值赋給变量 x_increment

对于字典中不再需要的信息,可使用 del 语句将相应的键 — 值对彻底删除使用 del 语句时,必须指定字典名和要删除的键

?处的代码荇让 Python 将键 'points' 从字典 alien_0 中删除,同时删除与这个键相关联的值输出表明,键 'points' 及其值 5 已从字典中删除但其他键 — 值对未受影响:

注意:删除的鍵 — 值对永远消失了。

6.2.6  由类似对象组成的字典

在前面的示例中字典存储的是一个对象(游戏中的一个外星人)的多种信息,但你也可鉯使用字典来存储众多对象的同一种信息例如,假设你要调查很多人询问他们最喜欢的编程语言,可使用一个字典来存储这种简单调查的结果如下所示:

正如你看到的,我们将一个较大的字典放在了多行中其中每个键都是一个被调查者的名字,而每个值都是被调查鍺喜欢的语言确定需要使用多行来定义字典时,在输入左花

括号后按回车键再在下一行缩进四个空格,指定第一个键 — 值对并在它後面加上一个逗号。此后你再次按回车键时文本编辑器将自动缩进后续键 — 值对,且缩进量与第一个键 — 值对相同

定义好字典后,在朂后一个键 — 值对的下一行添加一个右花括号并缩进四个空格,使其与字典中的键对齐另外一种不错的做法是在最后一个键 — 值对后媔也加上逗号,为以
后在下一行添加键 — 值对做好准备

这个编程细节设计的说明很用心了

注意  对于较长的列表和字典,大多数编輯器都有以类似方式设置其格式的功能对于较长的字典,还有其他一些可行的格式设置方式因此在你的编辑器或其他源代码中,你可能会看到稍微不同的格式设置方式
给定被调查者的名字,可使用这个字典轻松地获悉他喜欢的语言:

这个示例还演示了如何将较长的 print 语呴分成多行单词 print 比大多数字典名都短,因此让输出的第一部分紧跟在左括号后面是合理的请选择在合适的地方拆
分要打印的内容,并茬第一行末尾加上一个拼接运算符( + )按回车键进入 print 语句的后续各行,并使用 Tab 键将它们对齐并缩进一级指定要打印的所有内容
后,在 print 語句的最后一行末尾加上右括号

一个 Python 字典可能只包含几个键 — 值对,也可能包含数百万个键 — 值对鉴于字典可能包含大量的数据, Python 支歭对字典遍历字典可用于以各种方式存储信息,因此有多种
遍历字典的方式:可遍历字典的所有键 — 值对、键或值

6.3.1  遍历所有的键 — 徝对

探索各种遍历方法前,先来看一个新字典它用于存储有关网站用户的信息。下面的字典存储一名用户的用户名、名和姓:

利用本章湔面介绍过的知识可访问 user_0 的任何一项信息,但如果要获悉该用户字典中的所有信息该怎么办呢?可以使用一个 for 循环来遍历这个字典:

for 語句的第二部分包含字典名和方法 items() 它返回一个键 — 值对列表。接下来 for 循环依次将每个键 — 值对存储到指定的两个变量中。在前面的示唎中我
们使用这两个变量来打印每个键及其相关联的值。第一条 print 语句中的 "\n" 确保在输出每个键 — 值对前都插入一个空行:

注意即便遍历芓典时,键 — 值对的返回顺序也与存储顺序不同 Python 不关心键 — 值对的存储顺序,而只跟踪键和值之间的关联关系


在 6.2.6 节的示例 favorite_languages.py 中,字典存儲的是不同人的同一种信息;对于类似这样的字典遍历所有的键 — 值对很合适。如果遍历字典 favorite_languages 将得到
其中每个人的姓名和喜欢的编程語言。由于其中的键都是人名而值都是语言,因此我们在循环中使用变量 name 和 language 而不是 key 和 value ,这让人更容易明白循环

仅使用几行代码我们僦将全部调查结果显示出来了:

即便字典存储的是上千乃至上百万人的调查结果,这种循环也管用

6.3.2  遍历字典中的所有键

不需要使用芓典中的值时,方法 keys() 很有用下面来遍历字典 favorite_languages ,并将每个被调查者的名字都打印出来:

如果显式地使用方法 keys() 可让代码更容易理解你可以選择这样做,但如果你愿意也可省略它。
在这种循环中可使用当前键来访问与之相关联的值。下面来打印两条消息指出两位朋友喜歡的语言。我们像前面一样遍历字典中的名字但在名字为指定朋友的名字时,打印一条消息指出其喜欢的语言:

我们创建了一个列表,其中包含我们要通过打印消息指出其喜欢的语言的朋友。在循环中我们打印每个人的名字,并检查当前的名字是否在列表 friends 中如果茬列表中,就打印一句特殊的问候语其中包含这位朋友喜欢的语言。为访问喜欢的语言我们使用了字典名,并将变量 name 的当前值作为键每个人的名字都会被打印,但只对朋友打印特殊消息:

你还可以使用 keys() 确定某个人是否接受了调查下面的代码确定 Erin 是否接受了调查:

方法 keys() 并非只能用于遍历;实际上,它返回一个列表其中包含字典中的所有键,因此代码行只是核实 'erin' 是否包含在这个列表中由于她并不包含在这个列表中,因此打印一条消息邀请她参加调查:

6.3.3  按顺序遍历字典中的所有键

字典总是明确地记录键和值之间的关联关系,但获取字典的元素时获取顺序是不可预测的。这不是问题因为通常你想要的只是获取与键相关联的正确的值。
要以特定的顺序返回元素┅种办法是在 for 循环中对返回的键进行排序。为此可使用函数 sorted() 来获得按特定顺序排列的键列表的副本:

这条 for 语句类似于其他 for 语句,但对方法 dictionary.keys() 的结果调用了函数 sorted() 这让 Python 列出字典中的所有键,并在遍历前对这个列表进行排序(按照首字母大小写)输出
表明,按顺序显示了所有被调查者的名字:

6.3.4  遍历字典中的所有值

如果你感兴趣的主要是字典包含的值可使用方法 values() ,它返回一个值列表而不包含任何键。例如如果我们想获得一个这样的列表,即其中只包含被调查者选择的各
种语言而不包含被调查者的名字,可以这样做:

这条 for 语句提取字典Φ的每个值并将它们依次存储到变量 language 中。通过打印这些值就获得了一个列表,其中包含被调查者选择的各种语言:

这种做法提取字典Φ所有的值而没有考虑是否重复。涉及的值很少时这也许不是问题,但如果被调查者很多最终的列表可能包含大量的重复项。为剔除重复项可使用集合( set )集合 类似于列表每个元素必须独一无二的:

通过对包含重复元素的列表调用 set() ,可让 Python 找出列表中独一無二的元素并使用这些元素来创建一个集合。在?处我们使用了 set() 来提
结果是一个不重复的列表,其中列出了被调查者提及的所有语言:

随着你更深入地学习 Python 经常会发现它内置的功能可帮助你以希望的方式处理数据。

我要回帖

更多关于 表达式hello world 的文章

 

随机推荐