Python 3 初探,第 1 部分: Python 3 的新特性
2010-01-11 18:23
288 查看
Python 3 是 Guido van Rossum 功能强大的通用编程语言的最新版本。它虽然打破了与 2.x 版本的向后兼容性,但却清理了某些语法方面的问题。本文是系列文章中的第一篇,介绍了影响该语言及向后兼容性的各种变化,并且还提供了新特性的几个例子。
Python 版本 3,也被称为 Python 3000 或 Py3K(仿效 Microsoft® Windows® 2000 操作系统而命名的昵称)是 Guido van Rossum 通用编程语言的最新版本。虽然新版本对该核心语言做了很多改进,但还是打破了与 2.x 版本的向后兼容性。其他一些变化则是人们期待已久的,比如:
真正的除法 — 例如,1/2 返回的是 .5。
本文 — Python 3 系列文章中的第一篇 — 的内容涵盖了新的
新的 print() 函数
如今,您将需要让手指习惯于键入
让我们考虑这样的情况,即需要将标准输出(stdout)重定向到一个日志。如下的例子会打开文件 log.txt 以便进行追加并将对象指定给
另外一个例子是重定向给标准错误(sys.stderr):
上述两个例子都不错,但还有更好的解决方案。新的语法只要求给
这样的代码,语法更为清晰。另一个好处是通过向
总地来说,新的语法为:
其中,方括号(
从 raw_input() 到 input()
在 Python 版本 2.x 中,
与之不同,Python 2.x 中的
最初,曾有人建议将
将会变为:
对于一个简单输入而言,这太过繁琐,并且对于一个新手,这未免太难理解。往往需要向他们讲述模块 和导入 究竟是怎么回事、字符串输出以及句点操作符又是如何工作的(如此麻烦的话,与 Java™ 语言就没什么差别了)。所以,在 Python 3 内,将
有关 bytes 的简介
新的数据类型 bytes literal 及
例如:
会创建一个
如果初始化器(initializer)是一个字符串,那么就必须提供一种编码。如果初始化器是一个 bytes literal,则无须指定编码类型:请记住,bytes literal 并不是字符串。但是与字符串相似,可以连接多个字节:
用
也可以从文件中直接读取二进制数据。请看以下的代码:
它的功能是打开文件以便在二进制模式内读取一个文件对象,并在整个文件内进行读取。
字符串
Python 具有单一的字符串类型
在 Python 之前的版本内,
现在,它会返回一个 unicode 字符串:
正如我之前提到的,这个字符串是内置的字符串类型。
字符串对象和字节对象是不兼容的。如果想要得到字节的字符串表示,需要使用它的
字符串格式化方面的变化
很多 Python 程序员都感觉用来格式化字符串的这个内置的
它是一个二进制的操作符,最多只能接受两个参数。
除了格式化字符串参数,所有其他的参数都必须用一个元组(tuple)或是一个字典(dictionary)进行挤压。
这种格式化多少有些不灵活,所以 Python 3 引入了一种新的进行字符串格式化的方式(版本 3 保留了
字段 {0}、{1} 和 {2} 通过位置参数
下面是另外一个综合了位置参数和关键字参数的例子:
请记住,在关键字参数之后放置非关键字参数是一种语法错误。要想转义花括号,只需使用双倍的花括号,如下所示:
位置参数
新的
换言之,g 代表的是 一般格式,它输出的是宽度固定的值。小数点前的第一个数值指定的是最小宽度,小数点后的数值指定的是精度。format specifier 的完整语法超出了本文的讨论范围,更多信息,可以参见本文的 参考资料 小节。
内置 dict 类型的变化
3.0 内的另一个重大改变是字典内
注意:在 Python 内,集 是惟一元素的无序集合。
这里,我创建了具有两个键和值的一个字典,然后输出了
如下是在
不过,如果您的确想要得到值的列表,可以对所返回的
新的 I/O
在深入研究 I/O 的新机制之前,很有必要先来看看抽象基类( abstract base classes,ABC)。更深入的介绍将会在本系列的第 2 部分提供。
ABC 是一些无法被实例化的类。要使用 ABC,子类必须继承自此 ABC 并且还要覆盖其抽象方法。如果方法的前缀使用
清单 1. 一个简单的抽象基类
清单 2. 使用修饰符的一个抽象基类
了解了 ABC 之后,我们就可以继续探究新的 I/O 系统了。之前的 Python 发布版都缺少一些重要但是出色的函数,比如用于类似于流的对象的
打开一个流还是需要使用内置的
此内置
可能的模式有:
默认的模式是
默认的编码方式独立于平台。关闭文件描述符或
表 1. 针对不同打开模式的返回类型
请注意:文本模式可以是
清单 3 中所示的例子打开的是一个缓冲了的二进制流以供读取。
清单 3. 打开一个缓冲了的二进制流以供读取
结束语
Python 社区是否会接??版本 3 还尚在人们的猜测之中。打破向后兼容性意味着将要为两种版本提供支持。一些项目开发人员可能不太想迁移其项目,即便是使用版本 2 到 3 的转化器。就我个人而言,我发现从 Python 版本 2 迁移到 3 其实不过是对几个事情的重新认识:它当然不会像从 Python 迁移到 Java 或 Perl 语言那样变化强烈。很多变化是早就在人们意料中的,比如对
我 猜想,blogosphere 内的一些帖子会让 Python 的支持者也会误认为其中的某些变更 — 例如对向后兼容性的打破 — 具有破坏性的影响。 Lambda 本来就是准备好要删除的,只不过一直没有这么做,仍保留了其原始的格式。有关保留项目的完整列表,请访问 Python 核心开发站点。如果您具备足够的探索精神愿意深入研究所有的 PEP,那么您一定能够从中获得更深入的信息。
本系列的下一期文章将会涵盖更高级的主题,比如元类语法、ABC、修饰符、integer literal 支持、基类型和异常。
原文URL:http://www.ibm.com/developerworks/cn/linux/l-python3-1/
Python 版本 3,也被称为 Python 3000 或 Py3K(仿效 Microsoft® Windows® 2000 操作系统而命名的昵称)是 Guido van Rossum 通用编程语言的最新版本。虽然新版本对该核心语言做了很多改进,但还是打破了与 2.x 版本的向后兼容性。其他一些变化则是人们期待已久的,比如:
真正的除法 — 例如,1/2 返回的是 .5。
long和
int类型被统一为一种类型,删除了后缀 L。
True、
False和
None现在都是关键字。
本文 — Python 3 系列文章中的第一篇 — 的内容涵盖了新的
print()函数、
input()、输入/输出(I/O)的变化、新的
bytes数据类型、字符串和字符串格式化的变化以及内置的
dict类型的变化。本文面向的是那些熟悉 Python 并对新版本的变化很感兴趣但又不想费力读完所有 Python Enhancement Proposal(PEP)的编程人员。(本文后面的 参考资料 部分提供了有关这些 PEP 的链接。)
新的 print() 函数
如今,您将需要让手指习惯于键入
print("hello"),而不是原来的
print "hello",这是因为
让我们考虑这样的情况,即需要将标准输出(stdout)重定向到一个日志。如下的例子会打开文件 log.txt 以便进行追加并将对象指定给
fid。之后,利用
print>>将一个字符串重定向给文件
fid:
>>>fid = open("log.txt", "a") >>>print>>fid, "log text" |
另外一个例子是重定向给标准错误(sys.stderr):
>>>print>>sys.stderr, "an error occurred" |
上述两个例子都不错,但还有更好的解决方案。新的语法只要求给
print()函数的关键字参数
file传递一个值就可以了。比如:
>>>fid = open("log.txt", "a") >>>print("log.txt", file=fid) |
这样的代码,语法更为清晰。另一个好处是通过向
sep关键字参数传递一个字符串就能更改分割符(separator),通过向
end关键字参数传递另外一个字符串就能更改结束字符串。要更改分割符,可以利用:
>>>print("Foo", "Bar", sep="%") >>>Foo%Bar |
总地来说,新的语法为:
print([object, ...][, sep=' '][, end='endline_character_here'][, file=redirect_to_here]) |
其中,方括号(
[])内的代码是可选的。默认地,若只调用
print()自身,结果会追加一个换行符(
/n)。
|
在 Python 版本 2.x 中,
raw_input()会从标准输入(sys.stdin)读取一个输入并返回一个字符串,且尾部的换行符从末尾移除。下面的这个例子使用
raw_input()从命令提示符获取一个字符串,然后将值赋给
quest。
>>>quest = raw_input("What is your quest? ") What is your quest? To seek the holy grail. >>>quest 'To seek the holy grail.' |
与之不同,Python 2.x 中的
input()函数需要的是一个有效的 Python 表达式,比如 3+5。
最初,曾有人建议将
input()和
raw_input()从 Python 内置的名称空间一并删除,因此就需要进行导入来获得输入能力。这从方法上就不对;因为,简单键入:
>>>quest = input("What is your quest?") |
将会变为:
>>>import sys >>>print("What is your quest?") >>>quest = sys.stdin.readline() |
对于一个简单输入而言,这太过繁琐,并且对于一个新手,这未免太难理解。往往需要向他们讲述模块 和导入 究竟是怎么回事、字符串输出以及句点操作符又是如何工作的(如此麻烦的话,与 Java™ 语言就没什么差别了)。所以,在 Python 3 内,将
raw_input()重命名为
input(),这样一来,无须导入也能从标准输入获得数据了。如果您需要保留版本 2.x 的
input()功能,可以使用
eval(input()),效果基本相同。
|
新的数据类型 bytes literal 及
bytes对象的用途是存储二进制数据。此对象是 0 到 127 的不可修改的整数序列或纯粹的 ASCII 字符。实际上,它是版本 2.5 中
bytearray对象的不可修改版本。一个 bytes literal 是一个前面冠以 b 的字符串 — 例如,b'byte literal'。对 bytes literal 的计算会生成一个新的
bytes对象。可以用
bytes()函数创建一个新的
bytes对象。
bytes对象的构造函数为:
bytes([initializer[, encoding]]) |
例如:
>>>b = (b'/xc3/x9f/x65/x74/x61') >>>print(b) b'/xc3/x83/xc2/x9feta' |
会创建一个
bytes对象,但这是多余的,因为通过赋值一个 byte literal 就完全可以创建
bytes对象。(我只是想要说明这么做是可行的,但是我并不建议您这么做。)如果您想要使用 iso-8859-1 编码,可以尝试下面的做法:
>>>b = bytes('/xc3/x9f/x65/x74/x61', 'iso-8859-1') >>>print(b) b'/xc3/x83/xc2/x9feta' |
如果初始化器(initializer)是一个字符串,那么就必须提供一种编码。如果初始化器是一个 bytes literal,则无须指定编码类型:请记住,bytes literal 并不是字符串。但是与字符串相似,可以连接多个字节:
>>>b'hello' b' world' b'hello world' |
用
bytes()方法代表二进制数据以及被编码的文本。要将
bytes转变为
str,
bytes对象必须要进行解码(稍后会详细介绍)。二进制数据用
decode()方法编码。例如:
>>>b'/xc3/x9f/x65/x74/x61'.decode() 'ßeta' |
也可以从文件中直接读取二进制数据。请看以下的代码:
>>>data = open('dat.txt', 'rb').read() >>>print(data) # data is a string >>># content of data.txt printed out here |
它的功能是打开文件以便在二进制模式内读取一个文件对象,并在整个文件内进行读取。
|
Python 具有单一的字符串类型
str,其功能类似于版本 2.x 的 unicode 类型。换言之,所有字符串都是 unicode 字符串。而且 — 对非拉丁文的文本用户也非常方便 — 非-ASCII 标识符现在也是允许的。例如:
>>>césar = ["author", "consultant"] >>>print(césar) ['author', 'consultant'] |
在 Python 之前的版本内,
repr()方法会将 8-位字符串转变为 ASCII。例如:
>>>repr('é') "'//xc3//xa9'" |
现在,它会返回一个 unicode 字符串:
>>>repr('é') "'é'" |
正如我之前提到的,这个字符串是内置的字符串类型。
字符串对象和字节对象是不兼容的。如果想要得到字节的字符串表示,需要使用它的
decode()方法。相反,如果想要从该字符串得到 bytes literal 表示,可以使用字符串对象的
encode()方法。
|
很多 Python 程序员都感觉用来格式化字符串的这个内置的
%操作符太有限了,这是因为:
它是一个二进制的操作符,最多只能接受两个参数。
除了格式化字符串参数,所有其他的参数都必须用一个元组(tuple)或是一个字典(dictionary)进行挤压。
这种格式化多少有些不灵活,所以 Python 3 引入了一种新的进行字符串格式化的方式(版本 3 保留了
%操作符和
string.Template模块)。字符串对象现在均具有一个方法
format(),此方法接受位置参数和关键字参数,二者均传递到 replacement 字段 。Replacement 字段在字符串内由花括号(
{})标示。replacement 字段内的元素被简单称为一个字段。以下是一个简单的例子:
>>>"I love {0}, {1}, and {2}".format("eggs", "bacon", "sausage") 'I love eggs, bacon, and sausage' |
字段 {0}、{1} 和 {2} 通过位置参数
eggs、
bacon和
sausage被传递给
format()方法。如下的例子显示了如何使用
format()通过关键字参数的传递来进行格式化:
>>>"I love {a}, {b}, and {c}".format(a="eggs", b="bacon", c="sausage") 'I love eggs, bacon, and sausage' |
下面是另外一个综合了位置参数和关键字参数的例子:
>>>"I love {0}, {1}, and {param}".format("eggs", "bacon", param="sausage") 'I love eggs, bacon, and sausage' |
请记住,在关键字参数之后放置非关键字参数是一种语法错误。要想转义花括号,只需使用双倍的花括号,如下所示:
>>>"{{0}}".format("can't see me") '{0}' |
位置参数
can't see me没有被输出,这是因为没有字段可以输出。请注意这不会产生错误。
新的
format()内置函数可以格式化单个值。比如:
>>>print(format(10.0, "7.3g")) 10 |
换言之,g 代表的是 一般格式,它输出的是宽度固定的值。小数点前的第一个数值指定的是最小宽度,小数点后的数值指定的是精度。format specifier 的完整语法超出了本文的讨论范围,更多信息,可以参见本文的 参考资料 小节。
|
3.0 内的另一个重大改变是字典内
dict.iterkeys()、
dict.itervalues()和
dict.iteritems()方法的删除。取而代之的是
.keys()、
.values()和
.items(),它们被进行了修补,可以返回轻量的、类似于集的容器对象,而不是键和值的列表。这样的好处是在不进行键和条目复制的情况下,就能在其上执行
set操作。例如:
>>>d = {1:"dead", 2:"parrot"} >>>print(d.items()) <built-in method items of dict object at 0xb7c2468c> |
注意:在 Python 内,集 是惟一元素的无序集合。
这里,我创建了具有两个键和值的一个字典,然后输出了
d.items()的值,返回的是一个对象,而不是值的列表。可以像
set对象那样测试某个元素的成员资格,比如:
>>>1 in d # test for membership True |
如下是在
dict_values对象的条目上进行迭代的例子:
>>>for values in d.items(): ... print(values) ... dead parrot |
不过,如果您的确想要得到值的列表,可以对所返回的
dict对象进行强制类型转换。比如:
>>>keys = list(d.keys()) >>>print(keys) [1,2] |
|
|
ABC 是一些无法被实例化的类。要使用 ABC,子类必须继承自此 ABC 并且还要覆盖其抽象方法。如果方法的前缀使用
@abstractmethod修饰符(decorator),那么此方法就是一个抽象方法。新的 ABC 框架还提供了
@abstractproperty修饰符以便定义抽象属性。可以通过导入标准库模块
abc来访问这个新框架。清单 1 所示的是一个简单的例子。
清单 1. 一个简单的抽象基类
from abc import ABCMeta class SimpleAbstractClass(metaclass=ABCMeta): pass SimpleAbstractClass.register(list) assert isinstance([], SimpleAbstractClass) |
register()方法调用接受一个类作为其参数并会让此 ABC 成为所注册类的子类。这一点可以通过在最后一行上调用
assert语句进行验证。清单 2 是使用修饰符的另外一个例子。
清单 2. 使用修饰符的一个抽象基类
from abc import ABCMeta, abstractmethod class abstract(metaclass=ABCMeta): @abstractmethod def absMeth(self): pass class A(abstract): # must implement abstract method def absMeth(self): return 0 |
了解了 ABC 之后,我们就可以继续探究新的 I/O 系统了。之前的 Python 发布版都缺少一些重要但是出色的函数,比如用于类似于流的对象的
seek()。 类似于流的对象 是一些具有
read()和
write()方法的类似于文件的对象 — 比如,socket 或文件。Python 3 具有很多针对类似于流的对象的 I/O 层 — 一个原始的 I/O 层、一个被缓冲的 I/O 层以及一个文本 I/O 层 — 每层均由其自身的 ABC 及实现定义。
打开一个流还是需要使用内置的
open(fileName)函数,但是也可以调用
io.open(fileName))。这么做会返回一个缓冲了的文本文件;
read()和
readline()会返回字符串(请注意,Python 3 内的所有字符串都是 unicode)。您也可以使用
open(fileName, 'b')打开一个缓冲了的二进制文件。在这种情况下,
read()会返回字节,但
readline()则不能用。
此内置
open()函数的构造函数是:
open(file,mode="r",buffering=None,encoding=None,errors=None,newline=None,closefd=True) |
可能的模式有:
r:读
w:打开供写入
a:打开供追加
b:二进制模式
t:文本模式
+:打开一个磁盘文件供更新
U:通用换行模式
默认的模式是
rt,即打开供读取的文本模式。
buffering关键字参数的期望值是以下三个整数中的一个以决定缓冲策略:
0:关闭缓冲
1:行缓冲
> 1:完全缓冲(默认)
默认的编码方式独立于平台。关闭文件描述符或
closefd可以是 True 或 False。如果是 False,此文件描述符会在文件关闭后保留。若文件名无法奏效的话,那么
closefd必须设为 True。
open()返回的对象取决于您所设置的模式。表 1 给出了返回类型。
表 1. 针对不同打开模式的返回类型
模式 | 返回对象 |
---|---|
文本模式 | TextIOWrapper |
二进制 | BufferedReader |
写二进制 | BufferedWriter |
追加二进制 | BufferedWriter |
读/写模式 | BufferedRandom |
w、
r、
wt、
rt等。
清单 3 中所示的例子打开的是一个缓冲了的二进制流以供读取。
清单 3. 打开一个缓冲了的二进制流以供读取
>>>import io >>>f = io.open("hashlib.pyo", "rb") # open for reading in binary mode >>>f # f is a BufferedReader object <io.BufferedReader object at 0xb7c2534c> >>>f.close() # close stream |
BufferedReader对象可以访问很多有用的方法,比如
isatty、
peek、
raw、
readinto、
readline、
readlines、
seek、
seekable、
tell、
writable、
write和
writelines。要想查看完整列表,可以在
BufferedReader对象上运行
dir()。
|
Python 社区是否会接??版本 3 还尚在人们的猜测之中。打破向后兼容性意味着将要为两种版本提供支持。一些项目开发人员可能不太想迁移其项目,即便是使用版本 2 到 3 的转化器。就我个人而言,我发现从 Python 版本 2 迁移到 3 其实不过是对几个事情的重新认识:它当然不会像从 Python 迁移到 Java 或 Perl 语言那样变化强烈。很多变化是早就在人们意料中的,比如对
dict的实质更改。执行
print()远比执行 Java 的
System.out.println()容易得多,学习起来也相对容易,所以的确能带来一些好处。
我 猜想,blogosphere 内的一些帖子会让 Python 的支持者也会误认为其中的某些变更 — 例如对向后兼容性的打破 — 具有破坏性的影响。 Lambda 本来就是准备好要删除的,只不过一直没有这么做,仍保留了其原始的格式。有关保留项目的完整列表,请访问 Python 核心开发站点。如果您具备足够的探索精神愿意深入研究所有的 PEP,那么您一定能够从中获得更深入的信息。
本系列的下一期文章将会涵盖更高级的主题,比如元类语法、ABC、修饰符、integer literal 支持、基类型和异常。
原文URL:http://www.ibm.com/developerworks/cn/linux/l-python3-1/
相关文章推荐
- Python 3 初探,第 1 部分: Python 3 的新特性
- Python 3 初探,第 1 部分: Python 3 的新特性
- Python 3.6部分新特性
- Python2.4新特性(部分)
- Python 3 初探,第 2 部分: 高级主题
- Python 3 初探,第 2 部分: 高级主题
- 十五分钟让你了解Python套路 ---- Python的基本语法和部分特性
- python初探
- Python——高级特性 切片
- Servlet 3.0异步特性初探
- python特性(二):迭代器与for语句
- 【Python】学习笔记——-4.0、高级特性
- Python os模块常用部分功能总结
- Python 爬虫初探
- 用 Dojo 的 Ajax 应用开发进阶教程,第 1 部分:JavaScript 技巧与高级特性
- Python中找出两个字符串相同的部分(LeetCode Problem 299
- Python 3.6.0 正式版发布附新特性详解
- Python机器学习----第5部分 集成学习
- Python游戏开发-01-初探
- Python开发初探