Skip to content

Latest commit

 

History

History
845 lines (520 loc) · 65.6 KB

File metadata and controls

845 lines (520 loc) · 65.6 KB

一、Python 的温和介绍

"Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime." – Chinese proverb

根据维基百科,计算机编程是:

"...a process that leads from an original formulation of a computing problem to executable computer programs. Programming involves activities such as analysis, developing understanding, generating algorithms, verification of requirements of algorithms including their correctness and resources consumption, and implementation (commonly referred to as coding) of algorithms in a target programming language."

简而言之,编码就是告诉计算机使用它能理解的语言做某事。

计算机是非常强大的工具,但不幸的是,它们不能独立思考。他们需要被告知一切:如何执行任务,如何评估条件以决定遵循哪条路径,如何处理来自设备(如网络或磁盘)的数据,以及如何在发生不可预见的情况时做出反应,例如,出现故障或丢失。

您可以使用多种不同的样式和语言编写代码。难吗?我会说。这有点像写作。每个人都可以学习如何写作,你也可以。但是,如果你想成为一名诗人呢?那么仅仅写作是不够的。你必须掌握一整套其他技能,这将需要更长的时间和更大的努力。

最后,一切都取决于你想走多远。编码不仅仅是把一些有用的指令放在一起。真是太多了!

好的代码简短、快速、优雅、易于阅读和理解、简单、易于修改和扩展、易于扩展和重构,并且易于测试。能够同时编写具有所有这些特性的代码需要时间,但好消息是,通过阅读本书,您正在朝着这一方向迈出第一步。我毫不怀疑你能做到。任何人都可以;事实上,我们一直在编程,只是我们没有意识到。

你想举个例子吗?

说你想煮速溶咖啡。你必须得到一个杯子,速溶咖啡罐,一个茶匙,水和水壶。即使你不知道,你也在评估大量数据。你要确保水壶里有水,水壶插上电源,杯子干净,罐子里有足够的咖啡。然后,你把水烧开,也许同时,你在杯子里放些咖啡。当水准备好了,你把它倒进杯子里,搅拌。

那么,这是如何编程的呢?

嗯,我们收集了资源(水壶、咖啡、水、茶匙和杯子),并验证了一些与之相关的条件(水壶已插好电源,杯子干净,咖啡充足)。然后我们开始了两个动作(煮沸水和把咖啡放进杯子里),当这两个动作都完成后,我们最后把水倒进杯子里搅拌,结束了这个过程。

你能看见吗?我刚刚描述了咖啡程序的高级功能。这并不难,因为这是大脑一整天都在做的事情:评估情况,决定采取行动,执行任务,重复其中的一些,然后在某个时候停止。清理对象,将其放回原处,等等。

你现在所需要的就是学习如何解构你在现实生活中自动执行的所有动作,以便计算机能够真正理解它们。你也需要学习一门语言来指导它。

这就是这本书的目的。我会告诉你怎么做,我会尝试通过许多简单但重点突出的例子(我最喜欢的类型)来做到这一点。

在本章中,我们将介绍以下内容:

  • Python 的特性和生态系统
  • 关于如何启动和运行 Python 和虚拟环境的指导原则
  • 如何运行 Python 程序
  • 如何组织 Python 代码和 Python 的执行模型

适当的介绍

当我教编码时,我喜欢参考真实世界;我相信它们能帮助人们更好地保留这些概念。然而,现在是时候更严格一点,从更技术的角度看什么是编码。

当我们编写代码时,我们是在指导计算机必须做的事情。行动发生在哪里?在许多地方:计算机内存、硬盘驱动器、网络电缆、CPU 等等。这是一个完整的世界,大部分时间是真实世界子集的表示。

如果你编写了一个允许人们在线购买衣服的软件,你就必须在程序的范围内代表真实的人、真实的衣服、真实的品牌、尺寸等等。

为此,您需要在正在编写的程序中创建和处理对象。一个人可以是一个物体。汽车是一个物体。一双袜子是一件物品。幸运的是,Python 非常了解对象。

任何对象都有两个主要特性:属性和方法。让我们以人对象为例。通常,在计算机程序中,您将把人表示为客户或员工。您针对他们存储的属性包括姓名、SSN、年龄、是否持有驾驶执照、电子邮件、性别等。在一个计算机程序中,为了将一个对象用于您所服务的目的,您存储了所有需要的数据。如果你正在编写一个销售衣服的网站,你可能想存储客户的身高、体重以及其他测量数据,以便为他们推荐合适的衣服。因此,属性是对象的特征。我们一直在用它们:你能把那支笔递给我吗?-哪一个?-黑色的。在这里,我们使用钢笔的黑色属性来识别它(很可能是蓝色和红色)。

方法是对象可以做的事情。作为一个人,我有等方法。我能做的所有事情都可以看作是代表我的对象的方法。

所以,既然您知道了对象是什么,并且它们公开了可以运行的方法和可以检查的属性,那么就可以开始编码了。事实上,编码只是管理那些生活在我们在软件中复制的世界子集中的对象。您可以随意创建、使用、重用和删除对象。

根据官方 Python 文档(中的数据模型章节 https://docs.python.org/3/reference/datamodel.html

"Objects are Python's abstraction for data. All data in a Python program is represented by objects or by relations between objects."

我们将在第 6 章OOP、装饰器和迭代器中更详细地了解 Python 对象。现在,我们只需要知道 Python 中的每个对象都有一个 ID(或标识)、一个类型和一个值。

一旦创建,对象的 ID 永远不会更改。它是它的唯一标识符,Python 在后台使用它来检索我们想要使用的对象。

类型也不会改变。类型告诉对象支持哪些操作以及可以分配给它的可能值。

我们将在第 2 章内置数据类型中看到 Python 最重要的数据类型。

该值可以更改,也可以不更改。如果可以,则称该对象为可变,如果不能,则称该对象为不可变

我们如何使用对象?当然,我们给它起了个名字!给对象命名时,可以使用该名称检索对象并使用它。

在更一般的意义上,数字、字符串(文本)、集合等对象与名称相关联。通常,我们说这个名称是一个变量的名称。您可以将变量视为一个盒子,可以用来保存数据。

所以,你拥有你所需要的所有物品;现在怎么办?我们需要使用它们,对吗?我们可能希望通过网络连接发送它们或将它们存储在数据库中。可能在网页上显示或将其写入文件。为了做到这一点,我们需要对用户填写表单、按下按钮、打开网页并执行搜索做出反应。我们通过运行代码、评估条件来选择要执行哪些部分、执行多少次以及在什么情况下执行来做出反应。

要做到这一切,基本上我们需要一种语言。这就是 Python 的用途。在本书中,我们将一起使用 Python 语言来指导计算机为我们做一些事情。

现在,这些理论材料已经够多了;让我们开始吧。

输入 Python

Python 是荷兰计算机科学家和数学家 Guido Van Rossum 的非凡创造,他决定在 1989 年圣诞节期间向世界赠送一个他正在玩的项目。这种语言在 1991 年左右出现在公众面前,从那时起,它已发展成为当今世界上使用的主要编程语言之一。

我 7 岁的时候开始编程,用的是 VIC-20 准将,后来被它的哥哥 64 准将取代。它的语言是BASIC。后来,我登陆了 Pascal、汇编、C、C++、java、javascript、Visual Basic、PHP、ASP、ASP.NET、C 语言和其他我甚至不记得的语言,但是只有当我登陆 Python 时,我才终于有了当你在商店找到合适的沙发时的感觉。当你所有的身体部位都在叫喊时,买这个!这个对我们来说太完美了!

我花了大约一天的时间才习惯。它的语法和我过去习惯的有点不同,但在克服了最初的不适感(比如穿新鞋)之后,我就爱上了它。深深地让我们看看原因。

关于 Python

在我们进入血淋淋的细节之前,让我们了解一下为什么会有人想要使用 Python(我建议您阅读维基百科上的 Python 页面,以获得更详细的介绍)。

在我看来,Python 概括了以下特性。

便携性

Python 无处不在,将程序从 Linux 移植到 Windows 或 Mac 通常只是修复路径和设置的问题。Python 是为可移植性而设计的,它负责处理接口后面的特定操作系统操作系统)怪癖,使您免于编写针对特定平台定制的代码的痛苦。

一致性

Python 非常符合逻辑且连贯。你可以看到它是由一位杰出的计算机科学家设计的。大多数情况下,如果您不知道某个方法是如何调用的,您可以猜测该方法是如何调用的。

你可能现在还没有意识到这有多重要,尤其是在刚开始的时候,但这是一个主要的特性。这意味着你的大脑中更少的混乱,更少的浏览文档,更少的编码时需要在大脑中映射。

开发人员生产力

根据 Mark Lutz(Po.t0.学习 Python,第五版 AuthT1,A.T.2 A.ReLyLy Media Po.T3),Python 程序通常是等效 java 或 C++代码大小的五分之一到三分之一。这意味着工作完成得更快。而且越快越好。更快意味着市场反应更快。更少的代码不仅意味着要写的代码更少,而且要读的代码更少(专业程序员读的代码比写的要多),要维护、调试和重构的代码更少。

另一个重要方面是 Python 运行时不需要冗长而耗时的编译和链接步骤,因此您不必等待看到工作结果。

庞大的图书馆

Python 有一个非常广泛的标准库(据说它附带了电池。如果这还不够的话,全世界的 Python 社区都维护着一系列第三方库,这些库是根据特定需求定制的,您可以在Python 包索引PyPI中自由访问。当您编写 Python 代码并意识到您需要某个特性时,在大多数情况下,至少有一个库已经为您实现了该特性。

软件质量

Python 非常注重可读性、一致性和质量。语言的一致性允许高可读性,这在当今编码更多地是集体努力而不是单独努力的情况下是至关重要的。Python 的另一个重要方面是其固有的多半径特性。您可以将其用作脚本语言,但也可以利用面向对象、命令式和函数式编程风格。它是多功能的。

软件集成

另一个重要方面是 Python 可以扩展并与许多其他语言集成,这意味着即使公司使用不同的语言作为其主流工具,Python 也可以作为需要以某种方式相互通信的复杂应用程序之间的粘合剂。这是一个高级主题,但在现实世界中,此功能非常重要。

满足与享受

最后,但并非最不重要的是,它有乐趣!使用 Python 很有趣。我可以写 8 个小时的代码,然后愉快而满意地离开办公室,与其他程序员不得不忍受的斗争格格不入,因为他们使用的语言无法为他们提供同样数量的精心设计的数据结构和构造。毫无疑问,Python 使编码变得有趣。乐趣可以促进动机和生产力。

这些就是我向大家推荐 Python 的主要原因。当然,还有许多其他的技术和高级特性我可以谈论,但它们并不真正适用于像这一节这样的介绍性部分。在这本书中,它们会自然而然地出现,一章又一章。

缺点是什么?

也许,Python 中唯一的缺点(不是由于个人喜好)是它的执行速度。通常,Python 比它的编译兄弟要慢。当您运行应用程序时,Python 的标准实现会生成一个名为 byte code(扩展名为.pyc)的源代码编译版本,然后由 Python 解释器运行。这种方法的优点是可移植性,由于 Python 不像其他语言那样编译到机器级别,我们为此付出了代价。

然而,Python 的速度在今天很少成为问题,因此不管这个次优的特性如何,它都被广泛使用。事实上,在现实生活中,硬件成本不再是一个问题,通常通过并行化任务来提高速度是很容易的;因此,原始执行速度通常是总体性能的次要因素。然而,当涉及到数字运算时,人们可以切换到更快的 Python 实现,例如 PyPy,它通过实现高级编译技术提供了平均五倍的加速(请参见http://pypy.org/ 供参考)。

在进行数据科学时,您很可能会发现与 Python 一起使用的库,例如PandasNumPy,由于它们的实现方式,实现了本机速度。

如果这不是一个足够好的论点,您可以始终认为 Python 已经被用来驱动服务的后端,例如 Spotify 和 Instagram,其中性能是一个值得关注的问题。尽管如此,Python 已经充分地完成了它的工作。

今天谁在使用 Python?

还没被说服?让我们来简要介绍一下今天使用 Python 的公司:谷歌,YouTube,Dropbox,雅虎!Zope Corporation、Industrial Light&Magic、Walt Disney Feature Animation、Blender 3D、Pixar、NASA、NSA、Red Hat、诺基亚、IBM、Netflix、Yelp、英特尔、思科、惠普、高通和摩根大通,仅举几例。

甚至像战场 2文明 IV夸克这样的游戏也使用 Python 实现。

Python 在许多不同的环境中使用,例如系统编程、web 编程、GUI 应用程序、游戏和机器人技术、快速原型、系统集成、数据科学、数据库应用程序等等。几所著名的大学也将 Python 作为计算机科学课程的主要语言。

建立环境

在我们讨论在您的系统上安装 Python 之前,让我告诉您我将在本书中使用哪个 Python 版本。

Python 2 与 Python 3

Python 有两个主要版本:过去的 Python 2 和现在的 Python 3。这两个版本虽然非常相似,但在某些方面不兼容。

在现实世界中,Python2 实际上远远不是过去。简而言之,尽管 Python3 从 2008 年就已经推出,但从版本 2 开始的过渡阶段还远远没有结束。这主要是因为 Python2 在业界得到了广泛的应用,当然,公司并不热衷于仅仅为了更新系统而更新系统,而是遵循的理念,如果系统没有损坏,就不要修复它。您可以在 web 上阅读有关这两个版本之间转换的所有信息。

阻碍转型的另一个问题是第三方图书馆的可用性。通常,Python 项目依赖于数十个外部库,当然,当您启动一个新项目时,您需要确保已经有一个版本 3 兼容的库来满足可能出现的任何业务需求。如果不是这样的话,在 Python3 中启动一个全新的项目意味着引入一个潜在的风险,这是许多公司都不愿意承担的。

不过,在编写本文时,大多数最广泛使用的库都已移植到 Python3,在大多数情况下,使用 Python3 启动项目是非常安全的。许多库已经重写,以便与两个版本兼容,主要利用了six库的功能(名称来源于乘法 2 x 3,因为从版本 2 移植到版本 3),这有助于根据所使用的版本反思和调整行为。根据 PEP 373(https://legacy.python.org/dev/peps/pep-0373/ ),Python2.7 的生命终结EOL)已经设置为 2020 年,不会有 Python2.8,因此,现在正是那些在 Python2 中运行项目的公司需要开始设计升级策略,以便在为时已晚之前迁移到 Python3 的时候。

在我的电脑盒(MacBook Pro)上,这是我拥有的最新 Python 版本:

>>> import sys
>>> print(sys.version)
3.7.0a3 (default, Jan 27 2018, 00:46:45)
[Clang 9.0.0 (clang-900.0.39.2)]

因此,您可以看到该版本是 Python 3.7 的 alpha 版本,将于 2018 年 6 月发布。前面的文本是我在控制台中键入的一些 Python 代码。我们一会儿再谈。

本书中的所有示例都将使用 Python 3.7 运行。尽管目前最终版本可能与我的版本略有不同,但我将确保在本书出版时,所有代码和示例都是 3.7 版本的最新版本。

有些代码也可以在 Python2.7 中运行,可以按原样运行,也可以稍作调整,但此时,我认为最好先学习 Python3,然后,如果需要,再学习它与 Python2 的区别,而不是相反。

不过,不要担心这个版本的问题;这在实践中并不是什么大问题。

安装 Python

我从来没有真正理解在一本书中有一个设置部分的意义,不管你必须设置什么。大多数情况下,从作者编写说明到您实际试用说明,几个月过去了。也就是说,如果你幸运的话。一个版本发生变化,事情可能不会按照书中描述的方式进行。幸运的是,我们现在有了网络,所以为了帮助您建立和运行,我将给您一些指导和目标。

我意识到,大多数读者可能更希望书中有指导原则。我怀疑这会让他们的生活变得更轻松,因为我坚信如果你想开始使用 Python,你必须投入最初的努力来熟悉生态系统。这是非常重要的,它将增强你面对前面章节内容的信心。如果你陷入困境,记住谷歌是你的朋友

设置 Python 解释器

首先,让我们谈谈你的操作系统。Python 是完全集成的,很可能已经安装在几乎所有 Linux 发行版中。如果您有一个 macOS,很可能 Python 也已经存在(但是,可能只有 Python 2.7),而如果您使用的是 Windows,则可能需要安装它。

要启动并运行 Python 和所需的库,需要一些手工工作。Linux 和 macOS 似乎是 Python 程序员最友好的操作系统;另一方面,Windows 是需要付出最大努力的。

我当前的系统是 MacBookPro,这是我在本书中以及 Python 3.7 中将要用到的。

您想要开始的地方是 Python 官方网站:https://www.python.org 。该网站提供官方 Python 文档和许多其他资源,您会发现这些资源非常有用。花点时间去探索它。

Another excellent, resourceful website on Python and its ecosystem is http://docs.python-guide.org. You can find instructions to set up Python on different operating systems, using different methods.

找到下载部分,然后为您的操作系统选择安装程序。如果您使用的是 Windows,请确保在运行安装程序时选中选项install pip(实际上,为了安全起见,我建议对安装程序持有的所有组件进行完整安装)。我们稍后再谈pip

现在系统中已经安装了 Python,目标是能够打开控制台并通过键入python来运行 Python 交互式 shell。

Please note that I usually refer to the Python interactive shell simply as the Python console.

要在 Windows 中打开控制台,请转到“开始”菜单,选择“运行”,然后键入cmd。如果在处理本书中的示例时遇到权限问题,请确保您正在使用管理员权限运行控制台。

在 macOS X 上,您可以通过转到应用程序|实用程序|终端来启动终端。

如果您使用的是 Linux,那么您就知道有关控制台的所有内容。

我将交替使用术语控制台来表示 Linux 控制台、Windows 命令提示符和 Macintosh 终端。我还将使用 Linux 默认格式指示命令行提示符,如下所示:

$ sudo apt-get update

如果您不熟悉这一点,请花一些时间学习有关控制台工作原理的基本知识。简而言之,在$符号之后,您通常会找到必须键入的指令。注意大写和空格,因为它们非常重要。

无论您打开什么控制台,在提示符处键入python,并确保 Python 交互式 shell 显示出来。键入exit()退出。请记住,如果您的操作系统预装了 Python 2.*的话,您可能需要指定python3

这大致就是您在运行 Python 时应该看到的内容(它将根据版本和操作系统的不同而在某些细节上发生变化):

$ python3.7
Python 3.7.0a3 (default, Jan 27 2018, 00:46:45)
[Clang 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

现在 Python 已经设置好,您可以运行它了,现在是时候确保您拥有另一个工具了,这对于学习本书中的示例是必不可少的:virtualenv。

关于 virtualenv

你可能已经猜到了它的名字,VirtualEnvironment是关于虚拟环境的。让我解释一下它们是什么以及为什么我们需要它们,让我用一个简单的例子来说明。

在系统上安装 Python,然后开始为客户端 X 开发网站。创建项目文件夹并开始编码。在此过程中,您还安装了一些库;例如,Django 框架,我们将在第 14 章Web 开发中深入了解。假设您为 ProjectX 安装的 Django 版本是 1.7.1。

现在,你的网站非常好,你得到了另一个客户 Y。她希望你建立另一个网站,所以你开始项目 Y,在这个过程中,你需要再次安装 Django。唯一的问题是,现在 Django 版本是 1.8,您无法在系统上安装它,因为这将取代您为 Project X 安装的版本。您不想冒引入不兼容问题的风险,因此您有两个选择:要么坚持使用您计算机上当前的版本,或者升级它,并确保第一个项目在新版本中仍然完全正常工作。

老实说,这两种选择都不是很吸引人,对吧?绝对不是。所以,这里有一个解决方案:virtualenv!

virtualenv 是一种允许您创建虚拟环境的工具。换句话说,它是一种创建独立 Python 环境的工具,每个环境都是一个文件夹,其中包含所有必要的可执行文件,以使用 Python 项目所需的包(暂时将包视为库)。

因此,您可以为 Project X 创建一个虚拟环境,安装所有依赖项,然后为 Project Y 创建一个虚拟环境,安装其所有依赖项而不必担心,因为您安装的每个库都位于相应虚拟环境的边界内。在我们的示例中,项目 X 将保存 Django 1.7.1,而项目 Y 将保存 Django 1.8。

It is of vital importance that you never install libraries directly at the system level. Linux, for example, relies on Python for many different tasks and operations, and if you fiddle with the system installation of Python, you risk compromising the integrity of the whole system (guess to whom this happened...). So take this as a rule, such as brushing your teeth before going to bed: always, always create a virtual environment when you start a new project.

要在系统上安装 virtualenv,有几种不同的方法。例如,在基于 Debian 的 Linux 发行版上,您可以使用以下命令安装它:

$ sudo apt-get install python-virtualenv

也许,最简单的方法是按照 virtualenv 官方网站上的说明进行操作:https://virtualenv.pypa.io

您会发现安装 virtualenv 最常见的方法之一是使用pip,这是一个包管理系统,用于安装和管理用 Python 编写的软件包。

As of Python 3.5, the suggested way to create a virtual environment is to use the venv module. Please see the official documentation for further information. However, at the time of writing, virtualenv is still by far the tool most used for creating virtual environments.

您的第一个虚拟环境

创建虚拟环境非常容易,但根据系统的配置方式以及希望虚拟环境运行的 Python 版本,需要正确运行该命令。当你想使用 virtualenv 时,你需要做的另一件事就是激活它。激活 VirtualEnvironment 基本上会在幕后产生一些路径杂耍,因此当您调用 Python 解释器时,实际上是在调用活动虚拟环境解释器,而不仅仅是系统解释器。

我将在我的 Macintosh 控制台上向您展示一个完整的示例。我们将:

  1. 在您的项目根目录下创建一个名为learn.pp的文件夹(在我的例子中,它是一个名为srv的文件夹,在我的主文件夹中)。请根据您喜欢的盒子设置调整路径。
  2. learn.pp文件夹中,我们将创建一个名为learnpp的虚拟环境。

Some developers prefer to call all virtual environments using the same name (for example, .venv). This way they can run scripts against any virtualenv by just knowing the name of the project they dwell in. The dot in .venv is there because in Linux/macOS prepending a name with a dot makes that file or folder invisible.

  1. 创建虚拟环境后,我们将激活它。Linux、macOS 和 Windows 之间的方法略有不同。
  2. 然后,我们将通过运行 Python 交互式 shell 来确保运行所需的 Python 版本(3.7.*)。
  3. 最后,我们将使用deactivate命令停用虚拟环境。

这五个简单的步骤将向您展示启动和使用项目所需的全部操作。

下面是一个示例,说明了这些步骤在 macOS 上的外观(注意,根据您的操作系统、Python 版本等,您可能会得到稍微不同的结果)(以#开头的命令是注释,为了可读性引入了空格,表示由于缺少空格而换行的位置):

fabmp:srv fab$ # step 1 - create folder
fabmp:srv fab$ mkdir learn.pp
fabmp:srv fab$ cd learn.pp

fabmp:learn.pp fab$ # step 2 - create virtual environment
fabmp:learn.pp fab$ which python3.7
/Users/fab/.pyenv/shims/python3.7
fabmp:learn.pp fab$ virtualenv -p/Users/fab/.pyenv/shims/python3.7 learnpp
Running virtualenv with interpreter /Users/fab/.pyenv/shims/python3.7
Using base prefix '/Users/fab/.pyenv/versions/3.7.0a3'
New python executable in /Users/fab/srv/learn.pp/learnpp/bin/python3.7
Also creating executable in /Users/fab/srv/learn.pp/learnpp/bin/python
Installing setuptools, pip, wheel...done.

fabmp:learn.pp fab$ # step 3 - activate virtual environment
fabmp:learn.pp fab$ source learnpp/bin/activate

(learnpp) fabmp:learn.pp fab$ # step 4 - verify which python
(learnpp) fabmp:learn.pp fab$ which python
/Users/fab/srv/learn.pp/learnpp/bin/python

(learnpp) fabmp:learn.pp fab$ python
Python 3.7.0a3 (default, Jan 27 2018, 00:46:45)
[Clang 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()

(learnpp) fabmp:learn.pp fab$ # step 5 - deactivate
(learnpp) fabmp:learn.pp fab$ deactivate
fabmp:learn.pp fab$

注意,我必须明确地告诉 virtualenv 使用 Python 3.7 解释器,因为在我的机器上,Python 2.7 是默认解释器。如果我没有这样做,我会有一个虚拟环境,使用 Python2.7 而不是 Python3.7。

您可以将步骤 2 的两个说明组合在一个命令中,如下所示:

$ virtualenv -p $( which python3.7 ) learnpp

在本例中,我选择显式详细,以帮助您理解过程的每一部分。

另一件需要注意的事情是,为了激活虚拟环境,我们需要运行/bin/activate脚本,该脚本需要来源。当脚本源于源于时,意味着它是在当前 shell 中执行的,因此其效果在执行后持续。这是非常重要的。还请注意,在激活虚拟环境后,提示符是如何变化的,在左侧显示其名称(以及在停用虚拟环境时它是如何消失的)。在 Linux 上,步骤是相同的,因此我不会在这里重复它们。在 Windows 上,情况略有变化,但概念是相同的。请参考 virtualenv 官方网站以获取指导。

此时,您应该能够创建和激活虚拟环境。请尝试在没有我指导的情况下创建另一个。熟悉这个过程,因为这是您将一直在做的事情:我们从不在系统范围内使用 Python,记得吗?这非常重要。

所以,随着脚手架的出现,我们准备进一步讨论 Python 以及如何使用它。在我们这样做之前,请允许我谈一谈控制台。

你的朋友,控制台

在这个 GUI 和触摸屏设备的时代,当一切都只需点击一次鼠标时,不得不求助于控制台之类的工具似乎有点可笑。

但事实是,每次你从键盘上取下右手(或者左手,如果你是左撇子)抓住鼠标并将光标移动到你想点击的地方,你都在浪费时间。使用控制台完成工作,尽管可能违反直觉,但会提高生产率和速度。我知道,你必须相信我。

速度和生产力很重要,就我个人而言,我并不反对鼠标,但还有一个非常好的理由,您可能希望熟悉控制台:当您开发最终出现在某台服务器上的代码时,控制台可能是唯一可用的工具。如果你和它交朋友,我向你保证,在最重要的时候,你永远不会迷路(通常,当网站关闭时,你必须很快调查到底发生了什么)。

所以这真的取决于你。如果你还没有决定,请允许我怀疑,并尝试一下。这比你想象的容易,你永远不会后悔。没有什么比一个优秀的开发人员在与服务器的 SSH 连接中迷失方向更令人遗憾的了,因为他们习惯于自己的自定义工具集,而且只习惯于此。

现在,让我们回到 Python。

如何运行 Python 程序

有几种不同的方式可以运行 Python 程序。

运行 Python 脚本

Python 可以用作脚本语言。事实上,它总是证明自己非常有用。脚本是通常执行以执行任务之类的操作的文件(通常尺寸较小)。许多开发人员最终拥有了自己的工具库,当他们需要执行任务时,他们会启动这些工具库。例如,您可以使用脚本以一种格式解析数据并将其呈现为另一种不同的格式。也可以使用脚本处理文件和文件夹。您可以创建或修改配置文件,等等。从技术上讲,没有多少事情不能在脚本中完成。

在服务器上,脚本在精确的时间运行是很常见的。例如,如果您的网站数据库需要每 24 小时清理一次(例如,存储用户会话的表,这些会话很快就会过期,但不会自动清理),您可以设置一个 Cron 作业,在每天凌晨 3:00 启动脚本。

According to Wikipedia, the software utility Cron is a time-based job scheduler in Unix-like computer operating systems. People who set up and maintain software environments use Cron to schedule jobs (commands or shell scripts) to run periodically at fixed times, dates, or intervals.

我有 Python 脚本来完成所有需要几分钟或更多时间手动完成的琐碎任务,在某个时候,我决定自动化。我们将在第 12 章GUI 和脚本中花一半时间介绍 Python 脚本。

运行 Python 交互式 shell

运行 Python 的另一种方法是调用交互式 shell。这是我们在控制台的命令行上键入python时已经看到的。

所以,打开一个控制台,激活你的虚拟环境(这应该是你的第二天性,对吧?),然后键入python。您将看到以下几行代码:

$ python
Python 3.7.0a3 (default, Jan 27 2018, 00:46:45)
[Clang 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

那些>>>是外壳的提示。他们告诉您 Python 正在等待您键入内容。如果您键入一条简单的指令,即一行中的内容,您将看到的就是这些。但是,如果您键入的内容需要多行代码,shell 会将提示更改为...,从而提供一个可视线索,表明您正在键入多行语句(或任何需要多行代码的内容)。

继续,试试看;让我们做一些基础数学:

>>> 2 + 4
6
>>> 10 / 4
2.5
>>> 2 ** 1024
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216

最后一次手术向你展示了一些不可思议的东西。我们将2提升为1024的能力,Python 处理这项任务一点也不麻烦。尝试在爪哇、C++或 C 语言中进行。除非您使用特殊的库来处理如此大的数字,否则它不会起作用。

我每天都使用交互式 shell。快速调试非常有用,例如,检查数据结构是否支持操作。或者检查或运行一段代码。

当您使用 Django(一个 web 框架)时,交互式 shell 与之耦合,允许您使用框架工具,检查数据库中的数据,以及其他许多事情。你会发现,在你即将开始的旅程中,交互式 shell 将很快成为你最亲爱的朋友之一。

另一个解决方案是使用集成开发环境空闲),它的图形布局更好。这是一个非常简单的 IDE,主要面向初学者。它的功能比控制台中的裸交互 shell 稍大一点,因此您可能希望对其进行探索。它在 Windows Python 安装程序中免费提供,您可以轻松地在任何其他系统中安装它。您可以在 Python 网站上找到有关它的信息。

Guido Van Rossum 以英国喜剧团体 Monty Python 的名字命名 Python,因此谣传 IDLE 这个名字是为了纪念 Monty Python 的创始成员之一 Eric IDLE。

将 Python 作为服务运行

除了作为脚本运行外,在 shell 的边界内,Python 还可以作为应用程序进行编码和运行。我们将在整本书中看到许多关于此模式的示例。稍后我们将进一步了解它,我们将讨论 Python 代码是如何组织和运行的。

将 Python 作为 GUI 应用程序运行

Python 也可以作为图形用户界面GUI运行。有几种可用的框架,其中一些是跨平台的,另一些是特定于平台的。在第 12 章GUI 和脚本中,我们将看到一个使用 Tkinter 创建的 GUI 应用程序的示例,Tkinter 是一个位于Tk之上的面向对象层(Tkinter 表示 Tk 接口)。

Tk is a GUI toolkit that takes desktop application development to a higher level than the conventional approach. It is the standard GUI for Tool Command Language (Tcl), but also for many other dynamic languages, and it can produce rich native applications that run seamlessly under Windows, Linux, macOS X, and more.

Tkinter 与 Python 捆绑在一起;因此,它使程序员能够轻松访问 GUI 世界,出于这些原因,我选择它作为本书中 GUI 示例的框架。

在其他 GUI 框架中,我们发现以下是使用最广泛的:

  • PyQt
  • wxPython
  • 皮格特克

详细描述它们超出了本书的范围,但您可以在 Python 网站(上找到所需的所有信息 https://docs.python.org/3/faq/gui.html 在*中,Python 有哪些独立于平台的 GUI 工具包?*部分。如果您正在寻找 GUI,请记住根据一些原则选择您想要的 GUI。确保他们:

  • 提供开发项目所需的所有功能
  • 在您可能需要支持的所有平台上运行
  • 依靠一个尽可能广泛和活跃的社区
  • 包装可轻松安装/访问的图形驱动程序/工具

Python 代码是如何组织的?

让我们稍微谈谈 Python 代码是如何组织的。在本节中,我们将进一步深入了解兔子洞,并介绍更多的技术名称和概念。

从基础开始,Python 代码是如何组织的?当然,您可以将代码写入文件中。当您保存扩展名为.py的文件时,该文件被称为 Python 模块。

If you're on Windows or macOS that typically hide file extensions from the user, please make sure you change the configuration so that you can see the complete names of the files. This is not strictly a requirement, but a suggestion.

在一个文件中保存软件工作所需的所有代码是不切实际的。该解决方案适用于脚本,脚本通常不超过几百行(并且通常比这短得多)。

一个完整的 Python 应用程序可以由数十万行代码组成,因此您必须将其分散到不同的模块中,这是更好的,但还远远不够。事实证明,即使这样,使用代码仍然是不切实际的。因此 Python 提供了另一种结构,称为,它允许您将模块分组在一起。包只不过是一个文件夹,它必须包含一个特殊的文件__init__.py,不需要保存任何代码,但需要它的存在才能告诉 Python 文件夹不仅仅是某个文件夹,实际上它是一个包(请注意,从 Python 3.3 开始,__init__.py模块不再严格要求)。

一如往常,一个例子将使所有这些更加清楚。我在我的图书项目中创建了一个示例结构,当我在控制台中键入时:

$ tree -v example

我得到了ch1/example文件夹内容的树表示,其中包含本章示例的代码。下面是一个非常简单的应用程序的结构:

example
├── core.py
├── run.py
└── util
 ├── __init__.py
 ├── db.py
 ├── math.py
 └── network.py

您可以看到,在这个示例的根目录中,我们有两个模块,core.pyrun.py,还有一个包:util。在core.py中,可能有我们应用程序的核心逻辑。另一方面,在run.py模块中,我们可能可以找到启动应用程序的逻辑。在util包中,我希望能找到各种实用工具,事实上,我们可以猜测模块的命名是基于它们所持有的工具类型:db.py将持有用于处理数据库的工具,math.py当然将持有数学工具(可能我们的应用程序处理金融数据),以及network.py可能会拥有在网络上发送/接收数据的工具。

如前所述,__init__.py文件只是告诉 Pythonutil是一个包,而不仅仅是一个文件夹。

如果这个软件仅仅是在模块中组织的,那么就很难推断出它的结构。我在ch1/files_only文件夹下放了一个模块示例;亲自去看看吧:

$ tree -v files_only

这向我们展示了一幅完全不同的画面:

files_only/
├── core.py
├── db.py
├── math.py
├── network.py
└── run.py

猜测每个模块的功能有点困难,对吗?现在,考虑这只是一个简单的例子,所以你可以猜测如果我们不能在包和模块中组织代码,那么理解一个实际应用会有多困难。

我们如何使用模块和包?

当开发人员编写应用程序时,他们可能需要在应用程序的不同部分应用相同的逻辑。例如,当为来自用户可以在网页中填写的表单的数据编写解析器时,应用程序必须验证某个字段是否包含数字。不管这种验证的逻辑是如何编写的,很可能需要在多个地方使用它。

例如,在民意测验应用程序中,用户被问到许多问题,其中一些问题可能需要数字答案。例如:

  • 你几岁?
  • 你有多少宠物?
  • 你有几个孩子?
  • 你结过几次婚?

在我们期望得到数字答案的每个地方复制/粘贴(或者更恰当地说:复制)验证逻辑是非常糟糕的做法。这将违反不要重复自己DRY)原则,即在应用程序中不应重复同一段代码超过一次。我觉得有必要强调这一原则的重要性:在应用程序中,同一段代码不应重复多次(双关语)。

重复同一条逻辑可能非常糟糕,有几个原因,最重要的原因是:

  • 逻辑中可能有一个 bug,因此,您必须在应用逻辑的每个地方纠正它。
  • 您可能希望修改执行验证的方式,并且再次必须在应用验证的每个地方更改验证。
  • 您可能会忘记修复/修改一条逻辑,因为您在搜索其所有出现的情况时遗漏了它。这将在应用程序中留下错误/不一致的行为。
  • 您的代码将超出需要的长度,这是没有充分理由的。

Python 是一种很棒的语言,它为您提供了应用所有编码最佳实践所需的所有工具。对于这个特定的示例,我们需要能够重用一段代码。为了能够重用一段代码,我们需要有一个为我们保存代码的结构,这样我们就可以在每次需要重复其中的逻辑时调用该结构。这个结构存在,它被称为函数

这里我不会深入讨论细节,所以请记住,函数是一块有组织的、可重用的代码,用于执行任务。根据函数所属的环境类型,函数可以采用多种形式和名称,但目前这并不重要。当我们能够欣赏它们时,我们将在书中看到细节。函数是应用程序中模块化的构建块,它们几乎是不可或缺的。除非您正在编写一个超级简单的脚本,否则您将一直使用函数。我们将在第 4 章中探讨函数,函数,代码的构建块。

Python 附带了一个非常广泛的库,正如我在几页前已经说过的那样。现在,也许是定义库的好时机:是一个函数和对象的集合,提供丰富语言能力的功能。

例如,在 Python 的math库中,我们可以找到过多的函数,其中一个是factorial函数,它当然计算数字的阶乘。

In mathematics, the factorial of a non-negative integer number N, denoted as N!, is defined as the product of all positive integers less than or equal to N. For example, the factorial of 5 is calculated as: 5! = 5 * 4 * 3 * 2 * 1 = 120 The factorial of 0 is 0! = 1, to respect the convention for an empty product.

因此,如果您想在代码中使用这个函数,您所要做的就是导入它并使用正确的输入值调用它。如果输入值和调用的概念现在还不是很清楚,不要太担心;请专注于导入部分。我们通过从库中导入我们需要的内容来使用库,然后使用它。

在 Python 中,要计算数字5的阶乘,我们只需要以下代码:

>>> from math import factorial
>>> factorial(5)
120

Whatever we type in the shell, if it has a printable representation, will be printed on the console for us (in this case, the result of the function call: 120).

那么,让我们回到我们的例子,有core.pyrun.pyutil等等的例子。

在我们的示例中,包util是我们的实用程序库。我们的定制实用工具带,用于存放我们在应用程序中需要的所有可重用工具(即功能)。其中一些将处理数据库(db.py),一些处理网络(network.py),还有一些将执行数学计算(math.py),这超出了 Python 的标准math库的范围,因此,我们必须自己编写代码。

我们将在专门的章节中详细介绍如何导入函数和使用它们。现在我们来讨论另一个非常重要的概念:Python 的执行模型

Python 的执行模型

在本节中,我将向您介绍一些非常重要的概念,例如范围、名称和名称空间。当然,您可以在官方语言参考中阅读有关 Python 执行模型的所有内容,但我认为它是非常技术性和抽象的,所以让我先给您一个不太正式的解释。

名称和名称空间

假设你正在找一本书,那么你就去图书馆向别人要你要的书。他们告诉你类似于二楼,第 X 区,第三排。所以你走上楼梯,寻找第 X 部分,依此类推。

如果进入一个图书馆,所有的书都在一个大房间里以随机顺序堆放在一起,那将是非常不同的。没有楼层,没有分区,没有行,没有秩序。拿一本书是非常困难的。

当我们编写代码时,我们遇到了同样的问题:我们必须尝试并组织代码,以便事先不了解代码的人能够轻松地找到他们想要的东西。当软件结构正确时,它也会促进代码重用。另一方面,无组织的软件更可能暴露分散的重复逻辑。

首先,让我们从这本书开始。我们根据书名引用一本书,用 Python 术语来说,这就是一个名字。Python 名称是最接近于其他语言所称变量的抽象。名称基本上是指对象,由名称绑定操作引入。让我们举一个简单的例子(注意,#后面的任何内容都是注释):

>>> n = 3  # integer number
>>> address = "221b Baker Street, NW1 6XE, London"  # Sherlock Holmes' address
>>> employee = {
...     'age': 45,
...     'role': 'CTO',
...     'SSN': 'AB1234567',
... }
>>> # let's print them
>>> n
3
>>> address
'221b Baker Street, NW1 6XE, London'
>>> employee
{'age': 45, 'role': 'CTO', 'SSN': 'AB1234567'}
>>> other_name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'other_name' is not defined 

我们在前面的代码中定义了三个对象(您还记得每个 Python 对象都有哪些三个特性吗?)

  • 整数n(类型:int、值:3
  • 字符串address(类型:str,值:福尔摩斯的地址)
  • 字典employee(类型:dict,值:包含三个键/值对的字典)

别担心,我知道你不应该知道什么是字典。我们将在第 2 章内置数据类型中看到,它是 Python 数据结构之王。

Have you noticed that the prompt changed from >>> to ... when I typed in the definition of employee? That's because the definition spans over multiple lines.

那么,naddressemployee是什么?它们是名称。我们可以用来在代码中检索数据的名称。它们需要保存在某个地方,以便在我们需要检索这些对象时,我们可以使用它们的名称来检索它们。我们需要一些空间来容纳它们,因此:名称空间!

因此,名称空间是从名称到对象的映射。例如,一组内置名称(包含在任何 Python 程序中始终可访问的函数)、模块中的全局名称以及函数中的本地名称。甚至对象的属性集也可以被视为名称空间。

名称空间的美妙之处在于,它们允许您清晰地定义和组织名称,而不会出现重叠或干扰。例如,与我们在库中查找的那本书相关联的命名空间可用于导入该书本身,如下所示:

from library.second_floor.section_x.row_three import book 

我们从library名称空间开始,通过点(.操作符)进入该名称空间。在这个名称空间中,我们查找second_floor,然后再次使用.操作符进入它。然后我们进入section_x,最后在最后一个名称空间row_three中,我们找到了我们想要的名称:book

当我们处理真实的代码示例时,遍历名称空间会更清晰。现在,请记住名称空间是名称与对象关联的地方。

还有另一个概念,它与名称空间的概念密切相关,我想简单介绍一下:范围

范围

根据 Python 的文档:

A scope is a textual region of a Python program, where a namespace is directly accessible."

直接可访问意味着,当您查找对名称的非限定引用时,Python 会尝试在名称空间中查找该名称。

作用域是静态确定的,但实际上,在运行时,它们是动态使用的。这意味着,通过检查源代码,您可以知道对象的范围是什么,但这并不阻止软件在运行时更改该范围。Python 可以访问四个不同的作用域(当然,不一定所有作用域都同时存在):

  • local作用域,它是最内层的作用域,包含本地名称。
  • 封闭范围,即任何封闭函数的范围。它包含非本地名称,也包含非全局名称。
  • 全局范围包含全局名称。
  • 内置范围包含内置名称。Python 附带了一组可以以现成的方式使用的函数,如printallabs等等。它们生活在内置范围内。

规则如下:当我们引用一个名称时,Python 开始在当前名称空间中查找它。如果找不到名称,Python 将继续搜索封闭范围,直到搜索内置范围为止。如果在搜索内置作用域后没有找到名称,那么 Python 会引发一个NameError异常,这基本上意味着名称尚未定义(您在前面的示例中看到了这一点)。

因此,在查找名称时,名称空间的扫描顺序为:本地封闭全局内置LEGB)。

这都是非常理论化的,所以让我们看一个例子。为了向您展示本地名称空间和封闭名称空间,我必须定义几个函数。如果您目前不熟悉它们的语法,请不要担心。我们将在第 4 章中学习函数,函数,代码的构建块。请记住,在下面的代码中,当您看到def时,这意味着我正在定义一个函数:

# scopes1.py
# Local versus Global

# we define a function, called local
def local():
    m = 7
    print(m)

m = 5
print(m)

# we call, or `execute` the function local
local()

在前面的示例中,我们在全局范围和本地范围(由local函数定义的名称)中定义了相同的名称m。当我们使用以下命令执行此程序时(您是否激活了 virtualenv?):

$ python scopes1.py

我们在控制台上看到两个数字:57

所发生的是 Python 解释器从上到下解析文件。首先,它找到两个注释行,这些注释行被跳过,然后解析函数local的定义。调用此函数时,它会做两件事:为表示数字7的对象设置名称并打印。Python 解释器继续运行,并找到另一个名称绑定。这次绑定发生在全局范围内,值为5。下一行是对print函数的调用,该函数被执行(因此我们得到控制台上打印的第一个值:5

在此之后,将调用函数local。此时,Python 执行该函数,因此此时,绑定m = 7发生并打印出来。

需要注意的一件非常重要的事情是,属于local函数定义的代码部分在右边缩进了四个空格。实际上,Python 通过缩进代码来定义作用域。通过缩进进入作用域,通过取消缩进退出作用域。一些编码人员使用两个空格,其他人使用三个,但建议使用的空格数是四个。这是最大限度提高可读性的一个好方法。我们将进一步讨论在以后编写 Python 代码时应该采用的所有约定。

如果我们去掉那条m = 7线会发生什么?记住法律规则。Python 将开始在本地范围(函数local)中寻找m,如果没有找到它,它将转到下一个封闭范围。在本例中,下一个是全局函数,因为local周围没有封装函数。因此,我们会在控制台上看到两个数字5。让我们看看代码是什么样子的:

# scopes2.py
# Local versus Global

def local():
    # m doesn't belong to the scope defined by the local function
    # so Python will keep looking into the next enclosing scope.
    # m is finally found in the global scope
    print(m, 'printing from the local scope')

m = 5
print(m, 'printing from the global scope')

local()

运行scopes2.py将打印以下内容:

$ python scopes2.py
5 printing from the global scope
5 printing from the local scope

正如所料,Python 第一次打印m,然后调用函数local时,在其作用域中找不到m,因此 Python 会沿着 LEGB 链查找它,直到在全局作用域中找到m

让我们看一个额外层的示例,封闭范围:

# scopes3.py
# Local, Enclosing and Global

def enclosing_func():
    m = 13

    def local():
        # m doesn't belong to the scope defined by the local
        # function so Python will keep looking into the next
        # enclosing scope. This time m is found in the enclosing
        # scope
        print(m, 'printing from the local scope')

    # calling the function local
    local()

m = 5
print(m, 'printing from the global scope')

enclosing_func()

运行scopes3.py将在控制台上打印:

$ python scopes3.py
(5, 'printing from the global scope')
(13, 'printing from the local scope')

如您所见,函数local中的print指令与前面一样引用了mm仍然没有在函数本身中定义,因此 Python 按照 LEGB 顺序开始遍历范围。本次m在封闭范围内。

如果目前还不十分清楚,请不要担心。当我们阅读本书中的示例时,您会想到这一点。Python 教程的部分(https://docs.python.org/3/tutorial/classes.html 有一段关于作用域和名称空间的有趣段落。如果你想更深入地理解这个主题,一定要在某个时候阅读它。

在我们结束本章之前,我想再谈一谈对象。毕竟,Python 中的所有东西基本上都是一个对象,所以我认为它们应该得到更多的关注。

对象和类

当我在本章一节中介绍对象时,我说我们用它们来表示现实生活中的对象。例如,我们现在在网络上销售任何种类的商品,我们需要能够正确地处理、存储和表示这些商品。但事实上,物体远不止这些。在 Python 中,您将要做的大部分工作都与操作对象有关。

因此,在不深入太多细节的情况下(我们将在第 6 章OOP、Decorators 和迭代器中介绍),我想简单地向您介绍类和对象的解释。

我们已经看到,对象是 Python 对数据的抽象。事实上,Python 中的一切都是对象、事实上的数字、字符串(包含文本的数据结构)、容器、集合,甚至函数。您可以将它们视为至少具有三个特性的框:ID(唯一)、类型和值。

但是他们是如何活过来的呢?我们如何创建它们?我们如何编写自己的自定义对象?答案在于一个简单的词:

对象实际上是类的实例。Python 的美妙之处在于类本身就是对象,但我们不要走这条路。它引出了这种语言最高级的概念之一:元类。目前,获得类和对象之间差异的最佳方法是通过一个示例。

比如说一个朋友告诉你,我买了一辆新自行车!你立刻明白她在说什么。你看见那辆自行车了吗?不知道。你知道它是什么颜色吗?不。品牌?不。你知道这件事吗?不。但同时,为了理解你的朋友告诉你她买了一辆新自行车是什么意思,你知道你需要的一切。你知道自行车有两个轮子连在车架上,一个鞍座,踏板,把手,刹车等等。换句话说,即使你没有见过自行车本身,你也知道自行车的概念。一组抽象的特征和特征共同构成了一种称为自行车的东西。

在计算机编程中,这被称为。就这么简单。类用于创建对象。事实上,对象被称为类的实例。

换句话说,我们都知道自行车是什么;我们认识这个班。但是我有我自己的自行车,这是自行车课的一个例子。我的自行车是一个有自己特点和方法的物体。你有自己的自行车。相同的类,但不同的实例。世界上创造的每一辆自行车都是自行车类的实例。

让我们看一个例子。我们将编写一个类来定义一辆自行车,然后我们将创建两辆自行车,一辆红色,一辆蓝色。我会让代码非常简单,但如果你不了解它的所有内容,不要担心;此时您需要关心的是理解类和对象(或类实例)之间的区别:

# bike.py
# let's define the class Bike
class Bike:

    def __init__(self, colour, frame_material):
        self.colour = colour
        self.frame_material = frame_material

    def brake(self):
        print("Braking!")

# let's create a couple of instances
red_bike = Bike('Red', 'Carbon fiber')
blue_bike = Bike('Blue', 'Steel')

# let's inspect the objects we have, instances of the Bike class.
print(red_bike.colour)  # prints: Red
print(red_bike.frame_material)  # prints: Carbon fiber
print(blue_bike.colour)  # prints: Blue
print(blue_bike.frame_material)  # prints: Steel

# let's brake!
red_bike.brake()  # prints: Braking!

I hope by now I don't need to tell you to run the file every time, right? The filename is indicated in the first line of the code block. Just run $ python filename, and you'll be fine. But remember to have your virtualenv activated!

这里有很多有趣的事情值得注意。第一件事优先;类的定义与class语句一起发生。任何在class语句之后的代码,如果是缩进的,则称为类的主体。在我们的例子中,属于类定义的最后一行是print("Braking!")行。

定义了类之后,我们就可以创建实例了。您可以看到,类主体承载了两个方法的定义。方法基本上(简单地说)是属于类的函数。

第一种方法__init__初始值设定项。它使用一些 Python 魔术来设置对象,并使用我们在创建对象时传递的值。

Every method that has leading and trailing double underscores, in Python, is called a magic method. Magic methods are used by Python for a multitude of different purposes; hence it's never a good idea to name a custom method using two leading and trailing underscores. This naming convention is best left to Python.

我们定义的另一个方法brake只是一个附加方法的示例,如果我们想制动自行车,可以调用该方法。当然,它只包含一个print语句;这是一个例子。

我们当时创造了两辆自行车。一个是红色和碳纤维框架,另一个是蓝色和钢框架。我们在创造时传递这些价值观。创建后,我们打印出红色自行车的颜色属性和框架类型,蓝色自行车的框架类型,作为示例。我们也称之为red_bikebrake方法。

最后要注意的一件事。还记得我说过对象的属性集被认为是名称空间吗?我希望现在我的意思更清楚。您可以看到,通过不同的名称空间(red_bikeblue_bike)访问frame_type属性,我们可以获得不同的值。没有重叠,没有混乱。

点(.)操作符当然是我们进入名称空间的手段,在对象的情况下也是如此。

关于如何编写好代码的指南

编写好的代码并不像看上去那么容易。正如我之前所说的,好的代码暴露出一长串的质量,这些质量很难组合在一起。在某种程度上,编写好代码是一门艺术。无论你在这条路上的哪一个地方安顿下来,你都可以接受一些东西,这些东西会让你的代码立即变得更好:PEP 8

根据维基百科:

"Python's development is conducted largely through the Python Enhancement Proposal (PEP) process. The PEP process is the primary mechanism for proposing major new features, for collecting community input on an issue, and for documenting the design decisions that have gone into Python."

政治公众人物 8 可能是所有政治公众人物中最著名的。它提供了一组简单但有效的指导方针来定义 Python 美学,以便我们编写漂亮的 Python 代码。如果你从这一章中得到一个建议,请让它成为这样:使用它。拥抱它。你以后会感谢我的。

如今,编码不再是签入/签出业务。相反,这更多的是一种社会努力。几个开发人员通过 Git 和 Mercurial 等工具协作编写一段代码,结果是代码由许多不同的人编写。

Git and Mercurial are probably the distributed revision control systems that are most used today. They are essential tools designed to help teams of developers collaborate on the same software.

如今,我们比以往任何时候都更需要一种一致的代码编写方式,以便最大限度地提高可读性。当一家公司的所有开发人员都遵守 PEP8 时,他们中的任何一个在一段代码上登陆的人都会认为是自己编写的,这并不少见。事实上,它一直发生在我身上(我总是忘记我写的代码)。

这有一个巨大的优势:当您阅读本可以自己编写的代码时,您可以轻松地阅读它。如果没有约定,每个编码人员都会按照他们最喜欢的方式来构造代码,或者只是按照他们被教授或习惯的方式,这意味着必须按照其他人的风格来解释每一行代码。这就意味着要浪费更多的时间去理解它。多亏了政治公众人物 8,我们可以避免这种情况。我非常喜欢它,如果代码不尊重它,我就不会签署代码审查。所以,请花点时间来研究它;这很重要。

在本书的例子中,我将尽可能地尊重它。不幸的是,我没有 79 个字符(这是 PEP 8 建议的最大行长度),我将不得不减少空行和其他内容,但我向您保证,我将尝试布局我的代码,使其尽可能可读。

Python 文化

Python 已经被广泛应用于所有编码行业。它被许多不同的公司用于许多不同的目的,也被用于教育(这是一种非常好的语言,因为它有很多优点,而且很容易学习)。

Python 在今天如此流行的原因之一是,它周围的社区是巨大的、充满活力的,并且充满了才华横溢的人。世界各地组织了许多活动,主要围绕 Python 或其主要 web 框架 Django。

Python 是开放的,而且很多时候,拥抱它的人的思想也是开放的。查看 Python 网站上的社区页面,了解更多信息并参与其中!

Python 还有另一个方面,它围绕着Pythonic的概念。这与 Python 允许您使用其他地方没有的一些习惯用法有关,至少没有相同的形式或易于使用(当我不得不用一种现在不是 Python 的语言编写代码时,我感到非常幽闭恐惧)。

无论如何,这些年来,Pythonic 这个概念已经出现了,而且,按照我的理解,这是一种类似于用 Python 应该做的事情。

为了帮助您更多地了解 Python 文化和 Python 精神,我将向您展示 Python 的。非常受欢迎的可爱的复活节彩蛋。打开 Python 控制台并键入import this。以下是这一行的结果:

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

这里有两个阅读层次。一个是把它看作是一套有趣的指导方针。另一个是记住它,也许偶尔读一读,试图理解它是如何指更深层的东西的:一些 Python 特性,您必须深入理解这些特性,才能按照应该编写的方式编写 Python。从乐趣层面开始,然后深入挖掘。总是挖得更深。

关于 IDEs 的注记

关于 IDE 的几句话。要学习本书中的例子,你不需要一个;任何文本编辑器都可以。如果您想拥有更高级的特性,比如语法着色和自动完成,那么您必须为自己获取一个 IDE。您可以在 Python 网站上找到一个全面的开源 IDE 列表(只是 Google Python IDE)。我个人使用 Supreme 文本编辑器。免费试用,只需几美元。在我的生活中,我尝试了很多 IDE,但这是一个使我最有效率的 IDE。

两条重要建议:

  • 无论你选择使用哪种 IDE,都要努力学好它,这样你就可以利用它的优势,但不要依赖它。偶尔练习一下 VIM(或任何其他文本编辑器);学会在任何平台上使用任何一套工具做一些工作。
  • 无论您使用什么文本编辑器/IDE,在编写 Python 时,缩进是四个空格。不要使用制表符,不要将它们与空格混在一起。用四个空格,不是两个,不是三个,不是五个。只用四个。整个世界都是这样的,你不想因为喜欢三个空间的布局而成为一个被遗弃的人。

总结

在本章中,我们开始探索编程和 Python 的世界。我们几乎没有触及表面,只是一点点,涉及的概念将在本书后面更详细地讨论。

我们讨论了 Python 的主要特性,谁在使用它,用于什么,以及我们可以用什么不同的方式编写 Python 程序。

在本章的最后一部分,我们简要介绍了名称空间、作用域、类和对象的基本概念。我们还了解了如何使用模块和包组织 Python 代码。

在实践层面上,我们学习了如何在系统上安装 Python,如何确保我们拥有所需的工具,pip和 virtualenv,我们还创建并激活了第一个虚拟环境。这将允许我们在一个自包含的环境中工作,而不会危及 Python 系统的安装。

现在你准备好和我一起开始这段旅程了。你所需要的只是热情,一个活跃的虚拟环境,这本书,你的手指,和一些咖啡。

试着模仿这些例子;我会让它们简洁明了。如果你把它们放在指尖下,你会比仅仅阅读它们更好地保留它们。

在下一章中,我们将探讨 Python 丰富的内置数据类型集。有很多内容要涵盖,也有很多东西要学习!