详解Python 3.1新变化之核心语言篇

    来自:http://www.yqdown.com/chengxukaifa/shujujiegou/9701_6.htm 

  一、字符串的格式化 
  Python的最新版本为我们带来了讨人喜欢的格式字段的自动填数功能。我们知道,许多程序中经常须要 格式化字符串。Python 2.x版本运用 的是类似[s]printf函数的百分号操作符,如下所示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> '%s, %s!' % ('Hello', 'World')  'Hello, World!' 
  而Python 3.0则添加了更高级的字符串格式化功能,如下所示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> '{0}, {1}!'.format('Hello', 'World')  'Hello, World!' 
  如今,Python 3.1则在字符串格式化方面又有了新的改良 。对于Python 3.0来说,每当您想在格式串中引用位置参数时,您必须给出每个位置参数的索引。但是在Python 3.1中,您就可以将这些索引抛在脑后了,因为Python会依次替您填充这些参数: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> '{}, {}!'.format('Hello', 'World')  'Hello, World!'
  二、PEP-378:用于千位分隔符的格式说明符 
  在财务使用 程序中,通常要在数字中运用 千位分隔符。从事金融或者财会方面工作的人士是不这样写的“您欠我$12345678”,而是“您欠我$12,345,678”,他们惯于运用 逗号作为分隔符。那么,如何 运用 Python达到这种效果呢: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> format(12345678, ',')  '12,345,678' 
  您可以运用 其他区分符对数字执行 分组。这里的宽度说明符(这里为8)包括了逗号和小数点: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> format(12345.678, '8,.1f')  '12,345.7' 

 逗号通常作为默认的分隔字符,如果要运用 其他字符作为分隔字符的话,只需通过replace函数用您喜欢的字符替换逗号即可,具体如下所示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> format(1234, ',').replace(',', '_')  '1_234' 
  当然,您还可以运用 format函数来作为字符串要领 : Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> '{0:8,.1f}'.format(123.456)  ' 123.5' 
  三、Maketrans函数 
  运用 maketrans()和translate()函数,我们可以运用 一组字符来替换另一组字符。运用 这一替换功能时,多少有点繁琐,因为它要求运用 maketrans()函数(该函数的作用是把输入字符映射到输出字符)建立一个转换表,然后,再把这个转换表传递给translate()函数。当然,string模块仍然有它自己的maketrans()函数,不过Python 3.1不赞成运用 它,而是赞赏运用 单独的maketrans()函数来操作字节、字节数组和字符串。 
  下面的例子演示了如何 运用 maketrans()和translate()函数处理字节对象。须要 留心 的是,用于字节的转换表具有256个表项(每一项对应于一个可能的字节),并且这个例子把大部分字节都映射到它们自身,只有1,2和3例外,因为它们分别映射到了4,5和6。如下所示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> tt = bytes.maketrans(b'123', b'456')  >>> len(tt)  256  >>> tt  b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\  t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\  x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\  x1e\x1f !"#$%&\'()*+,-./0456456789:;<=>  ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcd  efghijklmnopqrstuvwxyz{}~\x7f\x80\x81\  x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\  x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\  x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\  xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\  xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\  xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\  xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\  xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\  xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\  xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\  xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\  xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\  xfa\xfb\xfc\xfd\xfe\xff'

建好转换表之后,我们只需把它传递给translate()函数即可,如下所示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> b'123456'.translate(tt)  b'456456' 
  我们还可以传递其它的参数作为要删除的字符: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> b'123456'.translate(tt, b'5')  b'45646' 
  我们可以看到,原来的5已经从123456从删掉了,但是转换得到的5(请记得 ,我们的映射表将2转化为5)并没有删除。这说明,系统是先从原来的字符串中删除相应的字符,然后才执行 的转换操作。 
  字符串的转换稍微有些不同,字符串版本的maketrans函数返回的是一个字典: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> tt = str.maketrans('123', '456')  {49: 52, 50: 53, 51: 54}  >>> '123456'.translate(tt)  '456456'
  四、与数学有关的变化 
  3.1版本在与数学有关的方面也有所改动 。 
  Int添加了一个bit_length要领 
  新版本中,int变量具有一个bit_length要领 ,它能返回该int变量以二进制数表示的时候的位数。例如,数字19的二进制表示为10011,那么它的位数就是5: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> int.bit_length(19)  5  >>> bin(19)  '0b10011' 
  浮点数的舍入 
  在Python 3.0以及早先的round()函数有点反复无常:如果您不指定精度的时候,它返回的是一个整数;如果指定精度的话,它返回的是您输入数据的类型: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> round(1000)  1000  >>> round(1000.0)  1000  >>> round(1000, 2)  1000  >>> round(1000.0, 2)  1000.0 
  在Python 3.1中,只要输入的数字是一个整数(即使它是用浮点数的形式表示的,例如1000.0),那么它总是返回一个整型数: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> round(1000)  1000  >>> round(1000.0)  1000  >>> round(1000, 2)  1000  >>> round(1000.0, 2)  1000 

浮点数的表示 
  目前,实数在大部分的硬件和操作系统中都是用32位(单精度)或者64位(双精度)来表示的。然而,这会导致一些实数不能 精确表示。由于计算机存储器的二进制特征 ,某些数字运用 十进制表示形式非常简洁,但是要是运用 浮点方案表示的话,就要复杂了。举例来说,运用 32位的单精度浮点数表示数字0.6,则为0.59999999999999998: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> 0.6  0.59999999999999998 
  对于这种表示方案,上面的数字是为了做到尽可能的精确,但是对用户来说却很不友好。 Python 3.1运用 了一个新算法,以便使得原值的表示尽可能得简练。所以在Python 3.1中,人们输入上面的数字,一个更简洁的表示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> 0.6  0.6 
  这已经很精确了,除非遇到算术运算。举例来说,表达式0.7+0.1的值用32位浮点表示法表示的话,它是 0.79999999999999993,而数字0.8的值用32位浮点数表示则是 0.80000000000000004。 这样一来,就意味着0.7+0.1并不等于0.8,这会导致一些疑问 。例如,下面的循环将永不休止: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> x = 0.0  >>> while x != 1.0:  ... print(repr(x))  ... x += 0.1 
  输出的结果: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  0  0.10000000000000001  0.20000000000000001  0.30000000000000004  0.40000000000000002  0.5  0.59999999999999998  0.69999999999999996  0.79999999999999993  0.89999999999999991  0.99999999999999989  1.0999999999999999  1.2  1.3  1.4000000000000001  1.5000000000000002  1.6000000000000003  ... 
  在Python 3.0中,repr()函数返回的是实际表示;而在Python 3.1中,它返回的是简洁表示。无论是在Python 3.0还是在Python 3.1中,print()函数显示的都是简洁表示: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> print(0.1)  0.1  >>> print(0.10000000000000001)  0.1 

Python语言还有一个称为decimal的模块,可用于精确的实数表示。它运用 一个不同的表示方案来表示浮点数,并且在内存运行的情况下,用尽量多的数位来表示一个实数——并且,当执行 算术的时候不会出现舍入误差。在Python 3.0中,Decimal类型运用 了一种新要领 来从一个字符串原始 化它表示的值;在Python 3.1中,又添加 了另一个新要领 即from_float()来接收浮点数。留心 ,即使当运用 from_float()的时候,Decimal模块也会比32位更精确。 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  >>> from decimal import Decimal  >>> Decimal.from_float(0.1)  Decimal('0.1000000000000000055511151231257827021181583404541015625') 
  五、改良 的WITH语句 
  在Python 2.5中,WITH语句是作为一个__future__特征 引入的,该语句的正式引入实际上是从Python 3.0开始的。到了Python 3.1版本,该语句已经能够支持更多的资源。最多见 的情形是,它可以打开输入、输出文件并在处理完成后关上 它们。在Python 3.0中,我们要么运用 嵌套的with语句,要么显式闭合在文件中。下面是一个Python 3.0的例子,它打开了一个输入文件,将其内容作为字符串读取,用字符串的title()要领 处理内容,并将结果写到一个输出文件中。 
  这个示例中含有两个嵌套的with语句,留心 嵌套的with语句中的最后一行。当代码试图读取out.txt的时候,结果为空,因为此文件是被缓冲处理的,并且还没有写入。当此with语句完成的时候,Python会关上 此文件,所以最后一行代码会认定out.txt的内容的确是大写文字。 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  open('in.txt', 'w').write('abc def')  with open('in.txt') as in_file:  with open('out.txt', 'w') as out_file:  text = in_file.read()  assert text == 'abc def'  text = text.title()  assert text == 'Abc Def'  out_file.write(text)  assert open('out.txt').read() == ''  assert open('out.txt').read() == 'Abc Def' 
  看到嵌套的with语句,是不是感觉有点头疼,呵呵。接下来,我们要打开两个两个文件,并在处理完成后关上 它们(如果您须要 打开三个文件,那么就须要 三个嵌套的with语句)。 Python 3.1运行您运用 单个WITH语句打开所有文件: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  open('in.txt', 'w').write('abc def')  with open('in.txt') as in_file:  with open('out.txt', 'w') as out_file:  text = in_file.read()  assert text == 'abc def'  text = text.title()  assert text == 'Abc Def'  out_file.write(text)  assert open('out.txt').read() == ''  assert open('out.txt').read() == 'Abc Def' 

Python 3.1的另一项改良 就是,gzip.GzipFile和bz2.BZ2File现在也可以 用于WITH语句。我们知道,这些都是压缩后的文件格式。下面的示例代码将运用 gzip文件和bz2文件来存储5000个字节的内容,并显示其尺寸。这里还有用到一些额外的Python 3特征 ,比如带有命名属性的统计结果和高级字符串格式化。 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->from bz2 import BZ2Filefrom gzip import GzipFileimport oswith GzipFile('1.gz', 'wb') as g, BZ2File('1.bz2', 'wb') as b:  g.write(b'X' * 5000)  b.write(b'X' * 5000)for ext in ('.gz', '.bz2'):  filename = '1' + ext  print ('The size of the {0} file is {1.st_size} bytes'.format(ext, os.stat(filename))) 
  输出的结果: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->The size of the .gz file is 43 bytesThe size of the .bz2 file is 45 bytes 
  六、小结 
  Python 3.0揭晓 七个月之后,Python核心开发人员于2009年6月27日揭晓 了新的Python 3.1版本。虽然此3.1版本只是对Python 3.0的一次小型升级,但是它不仅为开发者带来许多让人感兴趣的特征 ,同时在性能方面也有所改善。本文为读者细致 介绍了Python 3.1版本在核心语言方面的变化,在接下来的文章中,我们将继续为读者介绍新版本中标准程序库和性能改善方面的变化。 

posted @ 2010-12-21 10:33  Colin Xie  阅读(776)  评论(0编辑  收藏  举报