Python知识讲解Python版本3,也被称为Python3000或Py3K(仿效Microsoft®Windows®2000操作系统而命名的昵称)是GuidovanRossum通用编程语言的最新版本。虽然新版本对该核心语言做了很多改进,但还是打破了与2.x版本的向后兼容性。其他一些变化则是人们期待已久的,比如:真正的除法—例如,1/2返回的是.5。long和int类型被统一为一种类型,删除了后缀L。True、False和None现在都是关键字。本文—Python3系列文章中的第一篇—的内容涵盖了新的print()函数、input()、输入/输出(I/O)的变化、新的bytes数据类型、字符串和字符串格式化的变化以及内置的dict类型的变化。本文面向的是那些熟悉Python并对新版本的变化很感兴趣但又不想费力读完所有PythonEnhancementProposal(PEP)的编程人员。(本文后面的参考资料部分提供了有关这些PEP的链接。)新的print()函数如今,您将需要让手指习惯于键入print(hello),而不是原来的printhello,这是因为print现在是一个函数,不再是一个语句。我知道,这多少有点痛苦。我认识的每个Python程序员—一旦安装了版本3并得到“语法不正确”错误—都会郁闷地大叫。我知道这两个额外的符号十分讨厌;我也知道这将会破坏向后兼容性。但是这种改变还是有好处的。让我们考虑这样的情况,即需要将标准输出(stdout)重定向到一个日志。如下的例子会打开文件log.txt以便进行追加并将对象指定给fid。之后,利用print将一个字符串重定向给文件fid:fid=open(log.txt,a)printfid,logtext另外一个例子是重定向给标准错误(sys.stderr):printsys.stderr,anerroroccurred上述两个例子都不错,但还有更好的解决方案。新的语法只要求给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(Whatisyourquest?)Whatisyourquest?Toseektheholygrail.quest'Toseektheholygrail.'与之不同,Python2.x中的input()函数需要的是一个有效的Python表达式,比如3+5。最初,曾有人建议将input()和raw_input()从Python内置的名称空间一并删除,因此就需要进行导入来获得输入能力。这从方法上就不对;因为,简单键入:quest=input(Whatisyourquest?)将会变为:importsysprint(Whatisyourquest?)quest=sys.stdin.readline()对于一个简单输入而言,这太过繁琐,并且对于一个新手,这未免太难理解。往往需要向他们讲述模块和导入究竟是怎么回事、字符串输出以及句点操作符又是如何工作的(如此麻烦的话,与Java™语言就没什么差别了)。所以,在Python3内,将raw_input()重命名为input(),这样一来,无须导入也能从标准输入获得数据了。如果您需要保留版本2.x的input()功能,可以使用eval(input()),效果基本相同。回页首有关bytes的简介新的数据类型bytesliteral及bytes对象的用途是存储二进制数据。此对象是0到127的不可修改的整数序列或纯粹的ASCII字符。实际上,它是版本2.5中bytearray对象的不可修改版本。一个bytesliteral是一个前面冠以b的字符串—例如,b'byteliteral'。对bytesliteral的计算会生成一个新的bytes对象。可以用bytes()函数创建一个新的bytes对象。bytes对象的构造函数为:bytes([initializer[,encoding]])例如:b=(b'\xc3\x9f\x65\x74\x61')print(b)b'\xc3\x83\xc2\x9feta'会创建一个bytes对象,但这是多余的,因为通过赋值一个byteliteral就完全可以创建bytes对象。(我只是想要说明这么做是可行的,但是我并不建议您这么做。)如果您想要使用iso-8859-1编码,可以尝试下面的做法:b=bytes('\xc3\x9f\x65\x74\x61','iso-8859-1')print(b)b'\xc3\x83\xc2\x9feta'如果初始化器(initializer)是一个字符串,那么就必须提供一种编码。如果初始化器是一个bytesliteral,则无须指定编码类型:请记住,bytesliteral并不是字符串。但是与字符串相似,可以连接多个字节:b'hello'b'world'b'helloworld'用bytes()方法代表二进制数据以及被编码的文本。要将bytes转变为str,bytes对象必须要进行解码(稍后会详细介绍)。二进制数据用decode()方法编码。例如:b'\xc3\x9f\x65\x74\x61'.decode()'ßeta'也可以从文件中直接读取二进制数据。请看以下的代码:data=open('dat.txt','rb').read()print(data)#dataisastring#contentofdata.txtprintedouthere它的功能是打开文件以便在二进制模式内读取一个文件对象,并在整个文件内进行读取。回页首字符串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()方法。相反,如果想要从该字符串得到bytesliteral表示,可以使用字符串对象的encode()方法。回页首字符串格式化方面的变化很多Python程序员都感觉用来格式化字符串的这个内置的%操作符太有限了,这是因为:它是一个二进制的操作符,最多只能接受两个参数。除了格式化字符串参数,所有其他的参数都必须用一个元组(tuple)或是一个字典(dictionary)进行挤压。这种格式化多少有些不灵活,所以Python3引入了一种新的进行字符串格式化的方式(版本3保留了%操作符和string.Template模块)。字符串对象现在均具有一个方法format(),此方法接受位置参数和关键字参数,二者均传递到replacement字段。Replacement字段在字符串内由花括号({})标示。replacement字段内的元素被简单称为一个字段。以下是一个简单的例子:Ilove{0},{1},and{2}.format(eggs,bacon,sausage)'Iloveeggs,bacon,andsausage'字段{0}、{1}和{2}通过位置参数eggs、bacon和sausage被传递给format()方法。如下的例子显示了如何使用format()通过关键字参数的传递来进行格式化:Ilove{a},{b},and{c}.format(a=eggs,b=bacon,c=sausage)'Iloveeggs,bacon,andsausage'下面是另外一个综合了位置参数和关键字参数的例子:Ilove{0},{1},and{param}.format(eggs,bacon,param=sausage)'Iloveeggs,bacon,andsausage'请记住,在关键字参数之后放置非关键字参数是一种语法错误。要想转义花括号,只需使用双倍的花括号,如下所示:{{0}}.format(can'tseeme)'{0}'位置参数can'tseeme没有被输出,这是因为没有字段可以输出。请注意这不会产生错误。新的format()内置函数可以格式化单个值。比如:print(format(10.0,7.3g))10换言之,g代表的是一般格式,它输出的是宽度固定的值。小数点前的第一个数值指定的是最小宽度,小数点后的数值指定的是精度。formatspecifier的完整语法超出了本文的讨论范围,更多信息,可以参见本文的参考资料小节。回页首内置dict类型的变化3.0内的另一个重大改变是字典内dict.iterkeys()、dict.itervalues()和dict.iteritems()方法的删除。取而代之的是.keys()、.values()和.items(),它们被进行了修补,可以返回轻量的、类似于集的容器对象,而不是键和值的列表。这样的好处是在不进行键和条目复制的情况下,就能在其上执行set操作。例如:d={1:dead,2:parrot}print(d.items())built-inmethoditemsofdictobjectat0xb7c2468c注意:在Python内,集是惟一元素的无序集合。这里,我创建了具有两个键和值的一个字典,然后输出了d.items()的值,返回的是一个对象,而不是值的列表。可以像set对象那样测试某个元素的成员资格,比如:1ind#testformembershipTrue如下是在dict_values对象的条目上进行迭代的例子:forvaluesind.items():...print(values)...deadparrot不过,如果您的确想要得到值的列表,可以对所返回的dict对象进行强制类型转换。比如:keys=list(d.keys())print(keys)[1,2]回页首新的I/O元类Wikipedia对元类的定义是这样的,“一个元类是这样一个类,其实例也是类。”在本系列的第2部分我会对这个概念进行详细的介绍。在深入研究I/O的新机制之前,很有必要先来看看抽象基类(abstractbaseclasses,ABC)。更深入的介绍将会在本系列的第2部分提供。ABC是一些无法被实例化的类。要使用ABC,子类必须继承自此ABC并且还要覆盖其抽象方法。如果方法的前缀使用@ab