Python 指南

Python 指南

前言

目录

1. 开胃菜

2. 使用Python解释器

2.1 调用解释器

2.1.1 传递参数

2.1.2 交互模式

2.2 解释器及其工作模式

2.2.1 错误处理

2.2.2 执行 Python 脚本

2.2.3 源程序编码

2.2.4 交互环境的启动文件

3.初步认识 Python

3.1 像使用计算器一样使用Python

3.1.1 数值

3.1.2 字符串

3.1.3 Unicode 字符串

3.1.4 链表

3.2 开始编程

4. 流程控制

4.1 if 语法

4.2 for 语法

4.3 range() 函数

4.4 break 和 continue 语法以及 else 子句 在循环中的用法

4.5 pass 语法

4.6 定义函数

4.7 定义函数的进一步知识

4.7.1 定义参数变量

4.7.2 参数关键字

4.7.3 可变参数表

4.7.4 Lambda 形式

4.7.5 文档字符串

5. 数据结构

5.1 深入链表

5.1.1 将链表作为堆栈来使用

5.1.2 将链表作为队列来使用

5.1.3 函数化的编程工具

5.1.4 链表的内含(Comprehensions)

5.2 del 语法

5.3 Tuples 和 Sequences

5.4 字典(Dictionaries)

5.5 循环技巧

5.6 深入条件控制

5.7 Sequences 和其它类型的比较

6. 模块

6.1 深入模块

6.1.1 模块搜索路径

6.1.2 “编译” Python 文件

6.2 标准模块

6.3 dir() 函数

6.4 包

6.4.1 从包中导入所有内容(import * )

6.4.2 隐式包引用

6.4.3 包中的多重路径

7. 输入和输出

7.1 格式化输出

7.2 读写文件

7.2.1 文件对象的方法

7.2.2 pickle 模块

8. 错误和异常

8.1 语法 Errors

8.2 异常

8.3 捕获异常

8.4 释放异常

8.5 用户自定义异常

8.6 定义 Clean-up Actions

9. 类

9.1 有关术语的话题

9.2 Python 的作用域和命名空间

9.3 初识类

9.3.1 类定义语法

9.3.2 类对象

9.3.3 实例对象

9.3.4 方法对象

9.4 一些说明

9.5 继承

9.5.1 多继承

9.6 私有变量

9.7 补充

9.8 异常也是类

9.9 迭代子(Iterators)

9.10 发生器(Generators)

10. 接下来?

A. 交互式编辑和历史回溯

A.1 行编辑

A.2 历史回溯

A.3 快捷键绑定

A.4 注释

B. 浮点计算:问题与极限

B.1 表达错误

C. 历史和授权

C.1 本软件的历史

C.2 修改和使用Python的条件(Terms and conditions for accessing or otherwise using Python)

关于本文档
前言
Copyright & 2001, 2002, 2003 Python Software Foundation. All rights reserved.

Copyright & 2000 BeOpen.com. All rights reserved.

Copyright & 1995-2000 Corporation for National Research Initiatives. All rights reserved.

Copyright & 1991-1995 Stichting Mathematisch Centrum. All rights reserved.

See the end of this document for complete license and permissions information.

概要:
Python 是一种容易学习的强大语言。它包括了高效的高级数据结构,提供了一个简单但很有有效的方式以便进行面向对象编程。Python 优雅的语法,动态数据类型,以及它的解释器,使其成为了大多数平台上应用于各领域理想的脚本语言以及开发环境。

Python解释器及其扩展标准库的源码和编译版本可以从Python的Web站点http://www.python.org/及其所有镜像站上免费获得,并且可以自由发布。该站点上也提供了Python的一些第三方模块,程序,工具,以及附加的文档。

Python的解释器很容易通过C或C++(或者其它可以由C来调用的语言)来实现功能和数据结构的扩展。因些Python 也很适于做为定制应用的一种扩展语言。

这个手册介绍了一些Python语言及其系统的基本知识与根念。这有助于对Python有一个基本的认识,当然所有的例子都包括在里面了,所以这本手册很适合离线阅读。

需要有关标准对象和模块的详细介绍的话,请查询Python 程序库参考手册 文档。Python 参考手册 提供了更多的关于语言方面的正式说明。需要编写C或C++扩展,请阅读 Python 解释器的扩展和集成 以及Python/C API 参考手册。这几本书涵盖了各个深度上的Python知识。

本手册不会涵盖Python的所有功能,也不会去解释所用到的所有相关的知识。相反,它介绍了许多Python中最引人注目的功能,这会对读者掌握这门语言的风格大有帮助。读过它后,你应该可以阅读和编写Python模块和程序了,接下来你可以从Python 库参考手册中进一步学习Python复杂多变的库和模块了。
1. 开胃菜
如果你写过大规模的Shell脚本,应该会有过这样的体会:你还非常想再加一些别的功能进去,但它已经太大、太慢、太复杂了;或者这个功能需要调用一个系统函数,或者它只适合通过C来调用……通常这些问题还不足以严肃到需要用C重写这个Shell;可能这个功能需要一些类似变长字符串或其它一些在Shell脚本中很容易找到的数据类型(比如文件名的有序列表),但它们用C来实现就要做大量的工作,或者,你对C还不是很熟悉。

另一种情况:可能你需要使用几个C库来工作,通常C的编写/编译/测试/重编译周期太慢。你需要尽快的开发软件。也许你需要写一个使用扩展语言的程序,但不想设计一个语言,并为此编写调试一个解释器,然后再把它集成进你的程序。

遇到以上情况,Python可能就是你要找的语言。Python很容易上手,但它是一门真正的编程语言,提供了比Shell多的多的结构,支持大型程序。另一方面,它提供了比C更多的错误检查,并且,做为一门高级语言,它拥有内置的高级数据类型,例如可变数组和字典,如果通过C来实现的话,这些工作可能让你大干上几天的时间。因为拥有更多的通用数据类型,Python适合比Awk甚至Perl更广泛的问题领域,在其它的很多领域,Python至少比别的语言要易用得多。

Python可以让你把自己的程序分隔成不同的模块,这样就可以在其它的Python程序中重用。这样你就可以让自己的程序基于一个很大的标准模块集或者用它们做为示例来学习Python编程。Python中集成了一些类似文件I/O,系统调用,sockets,甚至像Tk这样的用户图形接口。

Python是一门解释型语言,因为不需要编译和链接的时间,它可以帮你省下一些开发时间。解释器可以交互式使用,这样就可以很方便的测试语言中的各种功能,以便于编写发布用的程序,或者进行自下而上的开发。还可以当它是一个随手可用的计算器。

Python可以写出很紧凑和可读性很强的程序。用Python写的程序通常比同样的C或C++程序要短得多,这是因为以下几个原因:

高级数据结构使你可以在一个单独的语句中表达出很复杂的操作;

语句的组织依赖于缩进而不是begin/end块;

不需要变量或参数声明。

Python是可执行的:如果你会用C语言写程序,那就可以很容易的为解释器添加新的集成模块和功能,或者优化瓶颈,使其达到最大速度,或者使Python能够链接到所需的二进制架构上(比如某个专用的商业图形库)。等你真正熟悉这一切了,你就可以把Python集成进由C写成的程序,把Python当做这个程序的扩展或命令行语言。

顺便说一下,这个语言的名字来源于BBC的“Monty Python's Flying Circus”节目,和凶猛的爬虫没有任何关系。在文档中引用Monty Python典故不仅是允许的,而且还受到鼓励!

现在你已经了解了Python中所有激动人心的东西,大概你想仔细的试试它了。学习一门语言最好的办法就是使用它,你会很乐于这样做。

下一节中,我们会很机械的说明解释器的用法。这没有什么神秘的,不过有助于我们练习后面展示的例子。

本指南其它部分通过例子介绍了Python语言和系统的各种功能,开始是简单表达式、语法和数据类型,接下来是函数和模块,最后是诸如异常和自定义类这样的高级内容。
2. 使用Python解释器
  
2.1 调用解释器
通常Python的解释器被安装在目标机器的 /usr/local/bin/python 目录下;把 /usr/local/bin 目录放进你的UNIX Shell 的搜索路径里,确保它可以通过输入

python
来启动。因为安装路径是可选的,所以也有可能安装在其它位置,你可以与安装Python的用户或系统管理员联系。(例如,/usr/local/python就是一个很常见的选择)

输入一个文件结束符(UNIX上是Ctrl+D,Windwos上是Ctrl+Z)解释器会以0值退出(就是说,没有什么错误,正常退出--译者)。如果这没有起作用,你可以输入以下命令退出:“import sys; sys.exit()”。

解释器的行编辑功能并不很复杂。装在Unix上的解释器可能会有GNU readline 库支持,这样就可以额外得到精巧的交互编辑和历史记录功能。可能检查命令行编辑器支持能力最方便的方式是在主提示符下输入Ctrl+P。如果有嘟嘟声(计算机扬声器),说明你可以使用命令行编辑功能,从附录 A 可以查到快捷键的介绍。如果什么也没有发声,或者P显示了出来,说明命令行编辑功能不可用,你只有用退格键删掉输入的命令了。

解释器的操作有些像Unix Shell:使用终端设备做为标准输入来调用它时,解释器交互的解读和执行命令,通过文件名参数或以文件做为标准输入设备时,它从文件中解读并执行脚本。

启动解释器的第三个方法是“python -c command [arg] ...”,这种方法可以在命令行中直接执行语句,等同于Shell的 -c选项。因为Python语句通常会包括空格之类的特殊字符,所以最好把整个语句用双引号包起来。

注意“python file”和“python <file”是有区别的。对于后一种情况,程序中类似于调用 input() 和raw_input()这样的输入请求,来自于确定的文件。因为在解析器开始执行之前,文件已经完全读入,所以程序指向文件尾。在前一种情况(这通常是你需要的)它们从来自于任何联接到Python解释器的标准输入,无论它们是文件还是其它设备。

使用脚本文件时,经常会运行脚本然后进入交互模式。这也可以通过在脚本之前加上-i参数来实现。(如果脚本来自标准输入,就不能这样运行,与前一段提到的原因一样。)

  
2.1.1 参数传递
调用解释器时,脚本名和附加参数之传入一个名为sys.argv的字符串列表。没有脚本和参数时,它至少也有一个元素:sys.argv[0]此时为空字符串。脚本名指定为‘ - ’(表示标准输入)时,sys.argv[0]被设置为‘ - ’,使用 -c 指令时,sys.argv[0]被设定为‘ -c ’。 -c 命令之后的参数不会被 Python 解释器的选项处理机制所截获,而是留在sys.argv 中,供脚本命令操作。

  
2.1.2 交互模式
从tty读取命令时,我们称解释器工作于交互模式。这种模式下它根据主提示符来执行,主提示符通常标识为三个大于号(“>;>;>; ”);继续的部分被称为从属提示符,由三个点标识(“... ”)。在第一行之前,解释器打印欢迎信息、版本号和授权提示:

python
Python 2.3 (#1, Jul 30 2003, 23:22:59)
[GCC 3.2 20020927 (prerelease)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>;>;>;
输入多行结构时需要从属提示符了,例如,下面这个 if 语句:

>;>;>; the_world_is_flat = 1
>;>;>; if the_world_is_flat:
...     print "Be careful not to fall off!"
...
Be careful not to fall off!
  
2.2 解释器及其环境
  
2.2.1 错误处理
有错误发生时,解释器打印一个错误信息和栈跟踪(监视)器?。交互模式下,它返回主提示符,如果从文件输入执行,它在打印栈跟踪器后以非零状态退出。(异常可以由try语句中的except子句来控制,这样就不会出现上文中的错误信息)有一些非常致命的错误会导致非零状态下退出,这由通常由内部矛盾和内存溢出造成。所有的错误信息都写入标准错误流;命令中执行的普通输出写入标准输出。

在主提示符或附属提示符输入中断符(通常是Control-C or DEL)就会取消当前输入,回到主命令行。2.1执行命令时输入一个中断符会抛出一个 KeyboardInterrupt 异常,它可以被try句截获。

  
2.2.2 执行Python脚本
BSD系统中,Python脚本可以像Shell脚本那样直接执行,只要在脚本文件开头写一行命令,指定文件和模式:

#! /usr/bin/env python
(将用户路径通知解释器) “#!”必须是文件的前两个字符,在某些平台上,第一行必须以Unix风格的行结束符(“\n”)结束,不能用Mac(“\r”)或Windows(“\r\n”)的结束符。注意,“#”是Python中是行注释的起始符。

脚本可以通过 chmod 命令指定执行模式和许可权。

$ chmod +x myscript.py
2.2.3 源程序编码
Python的源文件可以通过编码使用 ASCII 以外的字符集。 最好的做法是在 #! 行后面用一个特殊的注释行来定义字符集。

# -*- coding: iso-8859-1 -*-
根据这个声明,Python会将文件中的字符尽可能的从指定的编码转为Unicode,在本例中,这个字符集是 iso-8859-1 。在 Python 库参考手册 中可以找到可用的编码列表(根据我的实验,中文似乎只能用cp-936或utf-8,不直接支持GB,GBK,GB-18030或ISO-10646--译者注)。

如果你的文件编辑器支持UTF-8格式,并且可以保存UTF-8标记(aka BOM - Byte Order Mark),你可以用这个来代替编码声明(看来至少Jext还不支持这样做,而Vim,我还没找到它的编码设置在哪里,还是老老实实的用注释行指定源代码的编码吧--译者注)。IDLE可以通过设定Options/General/Default Source Encoding/UTF-8 来支持它。需要注意的是旧版Python不支持这个标记(Python 2.2或更早的版本),也同样不能使操作系统支持#!文件。

使用UTF-8内码(无论是用标记还是编码声明),我们可以在字符串和注释中使用世界上的大部分语言。标识符中不能使用非 ASCII 字符集。为了正确显示所有的字符,你一定要在编辑器中将文件保存为UTF-8格式,而且要使用支持文件中所有字符的字体。

  
2.2.4 交互式环境的启动文件
使用Python解释器的时候,我们可能需要在每次解释器启动时执行一些命令。你可以在一个文件中包含你想要执行的命令,设定一个名为PYTHONSTARTUP 的环境变量来指定这个文件。这类似于Unix shell的.profile文件。

这个文件在交互会话期是只读的,当Python从脚本中解读文件或以终端做为外部命令源时则不会如此(尽管它们的行为很像是处在交互会话期。)它与解释器执行的命令处在同一个命名空间,所以由它定义或引用的一切可以在解释器中不受限制的使用。你也可以在这个文件中改变sys.ps1和sys.ps2指令。

如果你想要在当前目录中执行附加的启动文件,你可以在全局启动文件中加入类似以下的代码:“if os.path.isfile('.pythonrc.py'): execfile('.pythonrc.py')”。 如果你想要在某个脚本中使用启动文件,必须要在脚本中写入这样的语句:

import os
filename = os.environ.get('PYTHONSTARTUP')
if filename and os.path.isfile(filename):
    execfile(filename)
3. Python的非正式介绍
在后面的例子中,区分输入和输出的方法是看是否有提示符(“>;>;>; ”和“.. ”):想要重复这些例子的话,你就要在提示符显示后输入所有的一切;没有以提示符开始的行,是解释器输出的信息。需要注意的是示例中的从属提示符用于多行命令的结束,它表示你需要输入一个空行。

本手册中的很多示例都包括注释,甚至有一些在交互提示符中折行。Python中的注释以符号“#”起始,一直到当前行的结尾。注释可能出现在一行的开始,也可能跟在空格或程序代码之后,但不会出现在字符串中,字符串中的#号只代表#号。

示例:

# this is the first comment
SPAM = 1                 # and this is the second comment
                         # ... and now a third!
STRING = "# This is not a comment."
  
3.1 初步认识Python
让我们试验一些简单的Python命令。启动解释器然后等待主提示符“>;>;>; ”出现(这用不了太久)。

  
3.1.1 数值
解释器的行为就像是一个计算器。你可以向它输入一个表达式,它会返回结果。表达式的语法简明易懂:+,-,*,/和大多数语言中的用法一样(比如C或Pascal),括号用于分组。例如:

>;>;>; 2+2
4
>;>;>; # This is a comment
... 2+2
4
>;>;>; 2+2  # and a comment on the same line as code
4
>;>;>; (50-5*6)/4
5
>;>;>; # Integer division returns the floor:
... 7/3
2
>;>;>; 7/-3
-3
像c一样,等号(“=”)用于给变量赋值。被分配的值是只读的。

>;>;>; width = 20
>;>;>; height = 5*9
>;>;>; width * height
900
同一个值可以同时赋给几个变量:

>;>;>; x = y = z = 0  # Zero x, y and z
>;>;>; x
0
>;>;>; y
0
>;>;>; z
0
Python完全支持浮点数,不同类型的操作数混在一起时,操作符会把整型转化为浮点数。

>;>;>; 3 * 3.75 / 1.5
7.5
>;>;>; 7.0 / 2
3.5
复数也同样得到了支持,虚部由一个后缀“j”或者“J”来表示。带有非零实部的复数记为“(real+imagj)”,或者也可以通过“complex(real, imag)”函数创建。

>;>;>; 1j * 1J
(-1+0j)
>;>;>; 1j * complex(0,1)
(-1+0j)
>;>;>; 3+1j*3
(3+3j)
>;>;>; (3+1j)*3
(9+3j)
>;>;>; (1+2j)/(1+1j)
(1.5+0.5j)
复数总是由实部和虚部两部分浮点数来表示。可能从 z.real 和 z.imag 得到复数z的实部和虚部。

>;>;>; a=1.5+0.5j
>;>;>; a.real
1.5
>;>;>; a.imag
0.5
用于向浮点数和整型转化的函数(float(), int() 和 long())不能对复数起作用--没有什么方法可以将复数转化为实数。可以使用abs(z)取得它的模,也可以通过z.real得到它的实部。

>;>;>; a=3.0+4.0j
>;>;>; float(a)
Traceback (most recent call last):
  File "<stdin>;", line 1, in ?
TypeError: can't convert complex to float; use e.g. abs(z)
>;>;>; a.real
3.0
>;>;>; a.imag
4.0
>;>;>; abs(a)  # sqrt(a.real**2 + a.imag**2)
5.0
>;>;>;
交互模式下,最近一次表达式输出保存在_变量中。这意味着把Python当做桌面计算器使用时,它可以更容易的进行连续计算,例如:

>;>;>; tax = 12.5 / 100
>;>;>; price = 100.50
>;>;>; price * tax
12.5625
>;>;>; price + _
113.0625
>;>;>; round(_, 2)
113.06
>;>;>;
这个变量对于用户来说是只读的。不要试图去给它赋值--由于Python的语法效果,你只会创建一个同名的局部变量覆盖它。

  
3.1.2 字符串
除了数值,Python还可以通过几种不同的方法操作字符串。字符串用单引号或双引号标识:

>;>;>; 'spam eggs'
'spam eggs'
>;>;>; 'doesn\'t'
"doesn't"
>;>;>; "doesn't"
"doesn't"
>;>;>; '"Yes," he said.'
'"Yes," he said.'
>;>;>; "\"Yes,\" he said."
'"Yes," he said.'
>;>;>; '"Isn\'t," she said.'
'"Isn\'t," she said.'
字符串可以通过几种方式分行。可以在行加反斜杠做为继续符,这表示下一行是当前行的逻辑沿续。

hello = "This is a rather long string containing\n\
several lines of text just as you would do in C.\n\
    Note that whitespace at the beginning of the line is\
significant."

print hello
注意换行用 \n 来表示;反斜杠后面的新行标识(newline,缩写“n”)会转换为换行符,示例会按如下格式打印:

This is a rather long string containing
several lines of text just as you would do in C.
    Note that whitespace at the beginning of the line is significant.
然而,如果我们创建一个“raw”行,\n序列就不会转为换行,示例源码最后的反斜杠和换行符n都会做为字符串中的数据处理。如下所示:

hello = r"This is a rather long string containing\n\
several lines of text much as you would do in C."

print hello
会打印为:

This is a rather long string containing\n\
several lines of text much as you would do in C.
或者,字符串可以用一对三重引号”””或'''来标识。三重引号中的字符串在行尾不需要换行标记,所有的格式都会包括在字符串中。

print """
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
"""
produces the following output:

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
解释器打印出来的字符串与它们输入的形式完全相同:内部的引号,用反斜杠标识的引号和各种怪字符,都精确的显示出来。如果字符串中包含单引号,不包含双引号,可以用双引号引用它,反之可以用单引号。(后面介绍的print语句,可以可以用来写没有引号和反斜杠的字符串)。

字符串可以用+号联接(或者说粘合),也可以用*号循环。

>;>;>; word = 'Help' + 'A'
>;>;>; word
'HelpA'
>;>;>; '<' + word*5 + '>;'
'<HelpAHelpAHelpAHelpAHelpA>;'
两个字符串值之间的联接是自动的,上例第一行可以写成“word = 'Help' 'A'”这种方式只对字符串值有效,任何字符串表达式都不适用这种方法。

>;>;>; import string
>;>;>; 'str' 'ing'                   #  <-  This is ok
'string'
>;>;>; string.strip('str') + 'ing'   #  <-  This is ok
'string'
>;>;>; string.strip('str') 'ing'     #  <-  This is invalid
  File "<stdin>;", line 1, in ?
    string.strip('str') 'ing'
                            ^
SyntaxError: invalid syntax
字符串可以用下标(索引)查询;就像C一样,字符串的第一个字符下标是0。这里没有独立的字符类型,字符仅仅是大小为一的字符串。就像在Icon中那样,字符串的子串可以通过切片标志来表示:两个由冒号隔开的索引。

>;>;>; word[4]
'A'
>;>;>; word[0]
'He'
>;>;>; word[2]
'lp'
切片索引可以使用默认值;省略前一个索引表示0,省略后一个索引表示被切片的字符串的长度。

>;>;>; word[]    # The first two characters
'He'
>;>;>; word[2:]    # All but the first two characters
'lpA'
和C字符串不同,Python字符串不能改写。按字符串索引赋值会产生错误。

>;>;>; word[0] = 'x'
Traceback (most recent call last):
  File "<stdin>;", line 1, in ?
TypeError: object doesn't support item assignment
>;>;>; word[] = 'Splat'
Traceback (most recent call last):
  File "<stdin>;", line 1, in ?
TypeError: object doesn't support slice assignment
然而,可以通过简单有效的组合方式生成新的字符串:

>;>;>; 'x' + word[1:]
'xelpA'
>;>;>; 'Splat' + word[4]
'SplatA'
切片操作有一个很有用的不变性: s[] + s[i:] 等于s。

>;>;>; word[] + word[2:]
'HelpA'
>;>;>; word[] + word[3:]
'HelpA'
退化的切片索引被处理的很优美:过大的索引代替为字符串大小,下界比上界大的返回空字符串。

>;>;>; word[1]
'elpA'
>;>;>; word[10:]
''
>;>;>; word[2]
''
索引可以是负数,计数从右边开始,例如:

>;>;>; word[-1]     # The last character
'A'
>;>;>; word[-2]     # The last-but-one character
'p'
>;>;>; word[-2:]    # The last two characters
'pA'
>;>;>; word[:-2]    # All but the last two characters
'Hel'
不过-0还是0,所以它不是从右边计数的!

>;>;>; word[-0]     # (since -0 equals 0)
'H'
越界的负切片索引会被截断,不过不要尝试在前元素索引(非切片的)中这样做:

>;>;>; word[-100:]
'HelpA'
>;>;>; word[-10]    # error
Traceback (most recent call last):
  File "<stdin>;", line 1, in ?
IndexError: string index out of range
理解切片的最好方式是把索引视为两个字符之间的点,第一个字符的左边是0,字符串中第n个字符的右边是索引n,例如:

+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0   1   2   3   4   5
-5  -4  -3  -2  -1
第一行是字符串中给定的0到5各个索引的位置,第二行是对应的负索引。从i到j的切片由这两个标志之间的字符组成。

对于非负索引,切片长度就是两索引的差。例如,word[1]的长度是2。

内置函数 len() 返回字符串长度:

>;>;>; s = 'supercalifragilisticexpialidocious'
>;>;>; len(s)
34
  
3.1.3 Unicode 字符串
从Python2.0开始,程序员们可以使用一种新的数据类型来存储文本数据:Unicode 对象。它可以用于存储多种Unicode数据(请参阅 http://www.unicode.org/ ),并且,通过必要时的自动转换,它可以与现有的字符串对象良好的结合。

Unicode针对现代和旧式的文本中所有的字符提供了一个序列。以前,字符只能使用256个序号,文本通常通过绑定代码页来与字符映射。这很容易导致混乱,特别是软件的国际化(internationalization--通常写做“i18n”--“i”+18 characters +“n”)。Unicode通过为所有字符定义一个统一的代码页解决了这个问题。

Python中定义一个Unicode字符串和定义一个普通字符串一样简单:

>;>;>; u'Hello World !'
u'Hello World !'
引号前小写的“u”表示这里创建的是一个Unicode字符串。如果你想加入一个特殊字符,可以使用Python的 Unicode-Escape 编码。如下例所示:

>;>;>; u'Hello\u0020World !'
u'Hello World !'
被替换的 \u0020 标识表示在给定位置插入编码值为 0x0020 的 Unicode字符(空格符)。

其它字符也会被直接解释成对应的Unicode码。如果你有一个在西方国家常用的Latin-1编码字符串,你可以发现Unicode字符集的前256个字符与Lation-1的对应字符编码完全相同。

另外,有一种与普通字符串相同的行模式。想要使用Python的Raw-Unicode-Escape 编码,你需要在字符串的引号前加上 ur 前缀。如果在小写“u”前可能有不止一个反斜杠,它只会把那些单独的 \uXXXX 转化为Unicode字符。

>;>;>; ur'Hello\u0020World !'
u'Hello World !'
>;>;>; ur'Hello\\u0020World !'
u'Hello\\\\u0020World !'
行模式在你需要输入很多个反斜杠时很有用,可能会用于正规表达式。

作为这些编码标准的一部分,Python提供了一个完备的方法集用于从已知的编码集创建Unicode字符串。

内置函数unicode() 提供了访问(编码和解码)所有已注册的Unicode编码的方法。它能转换众所周知的 Latin-1, ASCII, UTF-8, 和 UTF-16。后面的两个可变长编码字符集用一个或多个byte存储Unicode字符。默认的字符集是 ASCII ,它只处理0到127的编码,拒绝其它的字符并返回一个错误。当一个Unicode字符串被打印、写入文件或通过str()转化时,它们被替换为默认的编码。

>;>;>; u"abc"
u'abc'
>;>;>; str(u"abc"
'abc'
>;>;>; u"&&ü"
u'\xe4\xf6\xfc'
>;>;>; str(u"&&ü"
Traceback (most recent call last):
  File "<stdin>;", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(12
要把一个Unicode字符串用指定的字符集转化成8位字符串,可以使用Unicode对象提供的encode()方法,它有一个参数用以指定编码名称。编码名称小写。

>;>;>; u"&&ü".encode('utf-8')
'\xc3\xa4\xc3\xb6\xc3\xbc'
如果你有一个特定编码的字符串,想要把它转为Unicode字符集,,可以使用uncode()函数,它以编码名做为第二个参数。

>;>;>; unicode('\xc3\xa4\xc3\xb6\xc3\xbc', 'utf-8')
u'\xe4\xf6\xfc'
  
3.1.4 链表
Python 已经有了几个复合数据类型,用于组织其它的值。最通用的是链表,它写为中括之间用逗号分隔的一列值(子项),链表的子项不一定是同一类型的值。

>;>;>; a = ['spam', 'eggs', 100, 1234]
>;>;>; a
['spam', 'eggs', 100, 1234]
像字符串一样,链表也以零开始,可以被切片,联接,等等:

>;>;>; a[0]
'spam'
>;>;>; a[3]
1234
>;>;>; a[-2]
100
>;>;>; a[1:-1]
['eggs', 100]
>;>;>; a[] + ['bacon', 2*2]
['spam', 'eggs', 'bacon', 4]
>;>;>; 3*a[] + ['Boe!']
['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!']
与不变的字符串不同,链表可以改变每个独立元素的值:

>;>;>; a
['spam', 'eggs', 100, 1234]
>;>;>; a[2] = a[2] + 23
>;>;>; a
['spam', 'eggs', 123, 1234]
可以进行切片操作,甚至还可以改变链表的大小:

>;>;>; # Replace some items:
... a[0] = [1, 12]
>;>;>; a
[1, 12, 123, 1234]
>;>;>; # Remove some:
... a[0] = []
>;>;>; a
[123, 1234]
>;>;>; # Insert some:
... a[1] = ['bletch', 'xyzzy']
>;>;>; a
[123, 'bletch', 'xyzzy', 1234]
>;>;>; a[] = a     # Insert (a copy of) itself at the beginning
>;>;>; a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
内置函数len()也同样可以用于链表:

>;>;>; len(a)
8
它也可以嵌套链表(在链表中创建其它链表),例如:

>;>;>; q = [2, 3]
>;>;>; p = [1, q, 4]
>;>;>; len(p)
3
>;>;>; p[1]
[2, 3]
>;>;>; p[1][0]
2
>;>;>; p[1].append('xtra')     # See section 5.1
>;>;>; p
[1, [2, 3, 'xtra'], 4]
>;>;>; q
[2, 3, 'xtra']
注意最后一个例子,p[1]和q实际上指向同一个对象!我们在后面会讲到对象语法。

  
3.2 开始编程
当然,我们可以用Python做比2加2更复杂的事。例如,我们可以用以下的方法输出菲波那契(Fibonacci)序列的子序列:

>;>;>; # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>;>;>; while b < 10:
...       print b
...       a, b = b, a+b
...
1
1
2
3
5
8
示例中介绍了一些新功能:

第一行包括了复合参数:变量a和b同时被赋值为0和1。最后一行又一次使用了这种技术,证明了在赋值之前表达式右边先进行了运算。右边的表达式从左到右运算。

while循环运行在条件为真时执行。在Python中,类似于C任何非零值为真,零为假。 这个条件也可以用于字符串或链表,事实上于对任何序列类型,长度非零时为真,空序列为假。示例所用的是一个简单的比较。标准的比较运算符写法和C相同: < (小于),>; (大于),== (等于),<= (小于等于),>;=(大于等于)和!= (不等于)。

循环体是缩进的:缩进是Python对语句分组的方法。 Python仍没有提供一个智能编辑功能所以你要在每一个缩进行输入一个tab或(一个或多个)空格。 实际上你可能会准备更为复杂的文本编辑器来编写你的Python程序,大多数文本编辑器都提供了自动缩进功能。交互式的输入一个复杂语句时,需要用一个空行表示完成(因为解释器没办法猜出你什么时候输入最后一行)。需要注意的是每一行都要有相同的空字符来标识这是同一个语句块。

print语句打印给定表达式的值。它与你仅仅输入你需要的表达式(就像前面的计算器示例)不同,它可以同时输出多个表达式。字符串输出时没有引号,各项之间用一个空格分开,你可以很容易区分它们,如下所示:

>;>;>; i = 256*256
>;>;>; print 'The value of i is', i
The value of i is 65536
print语句末尾的逗号避免了输出中的换行:

>;>;>; a, b = 0, 1
>;>;>; while b < 1000:
...     print b,
...     a, b = b, a+b
...
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
需要注意的是,如果最后一行仍没有写完,解释器会在它打印下一个命令时插入一个新行。
4. 其它流程控制工具
除了前面介绍的 while 语句,Python 还从别的语言中借鉴了一些流程控制功能,并有所改变。

  
4.1 if 语句
也许最有句的语句类型是 if 语句。例如:

>;>;>; x = int(raw_input("lease enter an integer: ")
>;>;>; if x < 0:
...      x = 0
...      print 'Negative changed to zero'
... elif x == 0:
...      print 'Zero'
... elif x == 1:
...      print 'Single'
... else:
...      print 'More'
...
可能会有 0 或很多个 elif 部分,else 是可选的。关键字“elif ” 是“ else if ”的缩写,这个可以有效避免过深的缩进。if ... elif ... elif ... 序列用于替代其它语言中的 switch 或 case 语句。
您的帖子中有论坛禁止发表的词汇或内容!
4.3 range() 函数
如果你需要一个数值序列,内置函数range()可能会很有用,它生成一个等差级数链表。

>;>;>; range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(10)生成了一个包含10个值的链表,它准确的用链表的索引值填充了这个长度为10的列表,所生成的链表中不包括范围中的结束值。也可以让range操作从另一个数值开始,或者可以指定一个不同的步进值(甚至是负数,有时这也被称为“步长”):

>;>;>; range(5, 10)
[5, 6, 7, 8, 9]
>;>;>; range(0, 10, 3)
[0, 3, 6, 9]
>;>;>; range(-10, -100, -30)
[-10, -40, -70]
需要迭代链表索引的话,如下所示结合使用range()和len():

>;>;>; a = ['Mary', 'had', 'a', 'little', 'lamb']
>;>;>; for i in range(len(a)):
...     print i, a
...
0 Mary
1 had
2 a
3 little
4 lamb
4.4 break 和 continue 语句, 以及循环中的 else 子句
break语句和C中的类似,用于跳出最近的一级for或while循环。

continue 语句是从C中借鉴来的,它表示循环继续执行下一次迭代。

循环可以有一个else子句;它在循环迭代完整个列表(对于for)或执行条件为false(对于while)时执行,但循环被break中止的情况下不会执行。以下搜索素数的示例程序演示了这个子句:

>;>;>; for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...            print n, 'equals', x, '*', n/x
...            break
...     else:
...          # loop fell through without finding a factor
...          print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
  
4.5 pass 语句
pass 语句什么也不做。它用于那些语法上必须要有什么语句,但程序上什么也不要做的场合,例如:

>;>;>; while True:
...       pass # Busy-wait for keyboard interrupt
...
4.6 定义函数
我们可以编写一个函数来生成有给定上界的菲波那契数列:

>;>;>; def fib(n):    # write Fibonacci series up to n
...     """rint a Fibonacci series up to n."""
...     a, b = 0, 1
...     while b < n:
...         print b,
...         a, b = b, a+b
...
>;>;>; # Now call the function we just defined:
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
关键字def 引入了一个函数定义。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。函数体的第一行可以是一个字符串值,这个字符串是该函数的 文档字符串,也可称作docstring。  

有些文档字符串工具可以在线处理或打印文档,或让用户交互的浏览代码;在你的代码中加入文档字符串是一个好的作法,应该养成习惯。

调用函数时会为局部变量引入一个新的符号表。所有的局部变量都存储在这个局部符号表中。引用参数时,会先从局部符号表中查找,然后是全局符号表,然后是内置命名表。因此,全局参数虽然可以被引用,但它们不能在函数中直接赋值(除非它们用global语句命名)。

函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是传值调用(这里的值总是一个对象引用,而不是该对象的值)。4.1 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。

函数定义在当前符号表中引入函数名。作为用户定义函数,函数名有一个为解释器认可的类型值。这个值可以赋给其它命名,使其能句做为一个函数来使用。这就像一个重命名机制:

>;>;>; fib
<function object at 10042ed0>;
>;>;>; f = fib
>;>;>; f(100)
1 1 2 3 5 8 13 21 34 55 89
你可能认为fib不是一个函数(function),而是一个过程(procedure)。Python和C一样,过程只是一个没有返回值的函数。实际上,从技术上讲,过程也有一个返回值,虽然是一个不讨人喜欢的。这个值被称为 None (这是一个内置命名)。如果一个值只是None的话,通常解释器不会写一个None出来,如果你真想要看它的话,可以这样做:

>;>;>; print fib(0)
None
以下示列演示了如何从函数中返回一个包含菲波那契数列的数值链表,而不是打印它:

>;>;>; def fib2(n): # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while b < n:
...         result.append(b)    # see below
...         a, b = b, a+b
...     return result
...
>;>;>; f100 = fib2(100)    # call it
>;>;>; f100                # write the result
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
和以前一样,这个例子演示了一些新的Python功能: