Python 3 是 Guido van
Rossum 功能强大的通用编程语言的最新版本。它虽然打破了与 2.x 版本的向后兼容性,但却清理了某些语法方面的问题。本文是系列文章中的第一篇,介绍了影响该语言及向后兼容性的各种变化,并且还提供了新特性的几个例子。
Python 版本 3,也被称为Python 3000或Py3K(仿效
Microsoft® Windows® 2000 操作系统而命名的昵称)是 Guido van Rossum 通用编程语言的最新版本。虽然新版本对该核心语言做了很多改进,但还是打破了与 2.x 版本的向后兼容性。其他一些变化则是人们期待已久的,比如:
真正的除法 — 例如,1/2返回的是.5。
-
long
和int
类型被统一为一种类型,删除了后缀L。
本文 — Python 3 系列文章中的第一篇 — 的内容涵盖了新的print()
函数、input()
、输入/输出(I/O)的变化、新的bytes
数据类型、字符串和字符串格式化的变化以及内置的dict
类型的变化。本文面向的是那些熟悉
Python 并对新版本的变化很感兴趣但又不想费力读完所有 Python Enhancement Proposal(PEP)的编程人员。(本文后面的参考资料部分提供了有关这些
PEP 的链接。)
新的 print() 函数
如今,您将需要让手指习惯于键入print("hello")
,而不是原来的print
"hello"
,这是因为print
现在是一个函数,不再是一个语句。我知道,这多少有点痛苦。我认识的每个
Python 程序员 — 一旦安装了版本 3 并得到 “语法不正确” 错误 — 都会郁闷地大叫。我知道这两个额外的符号十分讨厌;我也知道这将会破坏向后兼容性。但是这种改变还是有好处的。
让我们考虑这样的情况,即需要将标准输出(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
)。
从 raw_input() 到 input()
在 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 的简介
新的数据类型 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 字符串:
正如我之前提到的,这个字符串是内置的字符串类型。
字符串对象和字节对象是不兼容的。如果想要得到字节的字符串表示,需要使用它的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 的完整语法超出了本文的讨论范围,更多信息,可以参见本文的参考资料小节。
内置 dict 类型的变化
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]
新的 I/O
在深入研究 I/O 的新机制之前,很有必要先来看看抽象基类( abstract base classes,ABC)。更深入的介绍将会在本系列的第 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()
。
原文地址:http://www.ibm.com/developerworks/cn/linux/l-python3-1/
分享到:
相关推荐
"Python3新特性.doc"文档详细阐述了Python 3相对于Python 2的主要改进和新增功能。Python 3引入了许多重大改变,如Unicode字符串的默认处理、print函数的引入、新的异常处理机制以及更现代的语法。了解这些新特性...
随着Python版本的更新迭代,每一次新版本的发布都会带来一些新特性或技巧,而Python 3作为当前主流版本,更是不断有新的技巧被开发和普及。以下,我们将详细讨论文中提及的Python技巧和新特性。 1. 拆箱功能...
本文分析了python3新特性函数注释Function Annotations用法。分享给大家供大家参考,具体如下: Python 3.X新增加了一个特性(Feature),叫作函数注释 Function Annotations 它的用途虽然不是语法级别的硬性要求,...
1. **Python 3新特性**:Python 3相较于Python 2有许多重要的改进和新特性。比如,统一的整数类型(int),不再区分long;print函数化,使用括号包裹参数;字符串采用Unicode编码,字符串不可变;异常处理语法的改变...
4. Python 3新特性的应用:第二版的出版标志着对Python 3新特性的更新和补充。书中应当讨论了Python 3的新特性,比如新的print语法、类型注解(type annotations)以及asyncio库等。 5. 高级编程概念:由于面向对象...
通过2to3工具和对Python3新特性的深入分析,教材为读者提供了在Python3环境下编程的坚实基础。对于已经是Python程序员的读者而言,此教材可以大大减少他们在升级到Python3时可能遇到的障碍,从而更加自信地展开...
11. **Python3新特性**:可能包括Python3较旧版本的新特性,如类型注解、async/await语法等。 12. **实战项目**:通过实际案例或练习,让读者将所学知识应用到实际问题解决中,提升编程能力。 这个带书签的高清...
八、Python3新特性 Python3相较于Python2有许多改进,如统一的整数类型、print函数、新的字符串编码处理、yield from关键字等。 通过阅读《深入python3》这本书,你将系统学习以上知识,并进一步了解Python 3的高级...
12. **Python 3新特性**:相对于Python 2,Python 3引入了许多新特性和改进,如print函数、新的字典和集合操作、生成器表达式等。 通过阅读《深入Python 3》,读者不仅可以系统学习Python 3的基础知识,还能了解其...
12. **Python3新特性**:详细介绍Python3相较于Python2的新增特性,如非本地作用域的变量查找规则、新的字符串格式化方式等。 《高级Python3编程指南》不仅适合已经有一定Python基础的开发者,也对希望深入学习...
给大家总结一下Python3一些新的更方便的特性!希望你们看完后也能高效率的编写代码 f-strings (3.6+) 在Python里面,我们经常使用format函数来格式化字符串,例如: user = Jane Doeaction = buylog_message = '...
2. 兼容模块:`future`提供了对Python 3新特性的模拟实现,如`print_function`、`division`、`generators`等,这些模块可以让Python 2代码具有Python 3的语法风格。 3. 高级API:包括`futures`模块(Python 2.7中的...
4. **第二版**:表明这是经过修订和更新的新版本,相比第一版可能包含了更多或更深入的内容,以及对Python 3新特性的补充。 ### 描述 虽然描述部分被重复多次,但从其中可以提炼出的关键信息是“Python 3程序开发...
10. **Python 3新特性**:Python 3引入了许多新特性,如非本地异常、新的字典和集合实现、yield from等,学习这些可以帮助跟上最新的编程实践。 在阅读《流畅的Python》教程时,你将通过一系列精心设计的例子,逐步...
《深入浅出 Python 3》这本书不仅适合已经熟悉 Python 2 的程序员升级技能,也适合想要深入了解 Python 3 新特性的初学者。书中通过丰富的案例和详尽的解释,帮助读者理解 Python 3 中的关键概念,尤其是字符串和...
10. **Python3新特性**:如果该书基于Python3,那么会详细介绍Python3与Python2的主要差异,如print函数的改变、新的字典和集合操作,以及新的语法特性等。 通过阅读《深入理解Python中文版高清(Dive into Python)...