原文: http://python3porting.com/improving.htmlhtml
译者: TheLover_Zpython
一旦你开始使用 Python 3,你就有机会接触新的特性来改善你的代码。这篇文章中提到的不少东西实际上在 Python 3 以前就已经被支持了。但我仍是要提一下它们,由于知道了这些之后你的代码能够从中获益。我说的包括修饰器,在 Python 2.2 开始提供支持; sorted()
方法,在 Python 2.4 开始提供支持;还有上下文管理,在 Python 2.5 开始提供支持。并发
这里说起的其它新特性在 Python 2.6 或者 2.7 都提供了支持,因此说若是你不是在用 Python 2.5 和以前的版本的话,你可使用这里提到的几乎所有的新特性。app
sorted()
来替代 .sort()
在 Python 中,列表有一个 .sort()
方法能够进行排序。 .sort()
会影响列表的结构。下面这么写是由于在 Python 2.3 以前只能这么写。函数
>>> infile = open('pythons.txt') >>> pythons = infile.readlines() >>> pythons.sort() >>> [x.strip() for x in pythons] ['Eric', 'Graham', 'John', 'Michael', 'Terry', 'Terry']
Python 2.4 开始加入了新的支持 sorted()
,它会返回一个排好序的列表而且接受和 .sort()
同样的参数。使用 sorted()
你能够避免改变列表的结构。它还能够接受迭代器做为输入而不仅是列表,这样可让你的代码看起来更棒。编码
>>> infile = open('pythons.txt') >>> [x.strip() for x in sorted(infile)] ['Eric', 'Graham', 'John', 'Michael', 'Terry', 'Terry']
然而,若是你把 mylist.sort()
替换为 mylist = sorted(mylist)
是没有用的,并且还会消耗更多的内存。url
2to3
有时会把 .sort()
改成 sorted()
。spa
从 Python 2.5 开始你可使用上下文管理器,它容许你创造和管理运行时内容。若是你以为听起来有点儿抽象,那就对了。上下文管理器确实很抽象而且很灵活,很容易被误用,我这就教你怎么正确运用它。.net
上下文管理器被用来看成 with
的一部分,在 with
的代码块内都有效。在代码块结束的时候上下文管理器退出。这可能听起来不是那么使人激动,除非我告诉你你可使用它来实现资源分配。你进入上下文的时候资源管理器分配资源,你退出的时候它释放资源。code
最经常使用的例子是读写文件。在大多数的更面向底层的语言中你必须记得关闭已打开的文件,但在 Python 中你不须要这么作。然而有时候你必须确认你关掉了文件,好比说你在循环中打开了许多文件以致于你用完了文件名。
>>> f = open('/tmp/afile.txt', 'w') >>> try: ... n = f.write('sometext') ... finally: ... f.close()
你也能够这么写,使用上下文管理器。
>>> with open('/tmp/afile.txt', 'w') as f: ... n = f.write('sometext')
当你使用上下文管理器的时候,代码块结束的时候文件就会自动关闭,就算是有错误发生也是这样。正如你所看到的那样,代码量少了不少,可是更重要的是程序看起来干净多了,也易读了。
另外一个例子是若是你想要重定向标准输出。正如前面同样,你会使用 try/except
。那样也不错,若是你只使用一次的话。可是若是你有不少次这样的需求的话,上下文管理器是你不二的选择。
>>> import sys >>> from StringIO import StringIO >>> class redirect_stdout: ... def __init__(self, target): ... self.stdout = sys.stdout ... self.target = target ... ... def __enter__(self): ... sys.stdout = self.target ... ... def __exit__(self, type, value, tb): ... sys.stdout = self.stdout ... >>> out = StringIO() >>> with redirect_stdout(out): ... print 'Test' ... >>> out.getvalue() == 'Test\n' True
碰到 with
语句之后 __enter__
方法被调用,退出的时候 __exit__()
被调用,包括引起错误。
上下文管理器在不少地方均可以使用。你的任何使用例外的代码最好确保资源或者全局变量没有被分配或者设置。
contextlib
库有各类各样的函数帮助你使用上下文管理器。好比说,若是你有一个有 .close()
方法但不是上下文管理器的对象,你可使用 closing()
函数来在 with
块结束的时候自动关闭它们。
>>> from contextlib import closing >>> import urllib >>> >>> book_url = ' >>> with closing(urllib.urlopen(book_url)) as page: ... print len(page.readlines()) 117
在 Python 3 和 2.6 中,一种新的字符串格式支持被引进了。它更灵活而且有更聪明的语法。
旧的字符串格式:
>>> 'I %s Python %i' % ('like', 2) 'I like Python 2'
新的字符串格式:
>>> 'I {0} Python {1}'.format('♥', 3)' I ♥ Python 3'
使用这些新特性你能够实现一些比较疯狂的小东西,可是玩过火的话你旧失去了它易读的优势:
>>> import sys >>> 'Python {0.version_info[0]:!<9.1%}'.format(sys) 'Python 300.0%!!!'
更详细的文档请参考 Common String Operations 。
旧的字符串格式基于 %
的这个特性可能最终会被移除,不过最终日期尚未定。
修饰器在 Python 2.4 的时候被支持,而后有了内置的修饰器好比说 @property
和 @classmethod
,修饰器开始变的流行。Python 2.6 引入了类修饰器。
类修饰器能够用来包裹类或者修饰类。一个例子就是 functools.total_ordering
,可让你实现最小的富比较操做符,而后增长到你的类。它们能够做为元类,类修饰器的例子就是修饰器能够把类变成一个单独的类。 zope.interface
类修饰器能够注册一个做为特定接口的类。
Python 3 中引入了一种新的集合语法。相对于 set([1, 2, 3])
你可使用更干净语法的 {1, 2, 3}
。两种语法在 Python 3 中均可以工做,可是更建议使用新的语法。
>>> set([1,2,3]){1, 2, 3}
yield
和 生成器就像浮点除法操做符和 .sort()
的 key
参数,生成器已经在不知不觉深刻了咱们的编码生活。虽然很少见,但它们仍是很是实用的,能够帮你节省内存,简化代码。咱们来看看这个例子:
>>> def allcombinations(starters, endings): ... result = [] ... for s in starters: ... for e in endings: ... result.append(s+e) ... return result
这么写就优雅多了:
>>> def allcombinations(starters, endings): ... for s in starters: ... for e in endings: ... yield s+e
生成器在 Python 2.2 开始加入支持,可是 Python 2.4 进行了一些改进。看起来很像是列表表达式,但并不返回列表而是返回表达式。它们在有列表表达式的地方几乎均可以使用。
>>> sum([x*x for x in xrange(2000000)]) 2666664666667000000L
能够写做:
>>> sum(x*x for x in xrange(2000000)) 2666664666667000000L
在 Python 3 和 2.6 中,生成器推导式被引进。它就是简单的一个带括号的生成器表达式,能够和列表推导式同样工做,返回一个生成器而不是列表。
>>> (x for x in 'Silly Walk') <generator object <genexpr> at ...>
在 Python 3 中生成器推导式不只仅是一个新的漂亮的特性,而是一个重要的改变,由于生成器推导式如今是其它全部内置推导式的基础。在 Python 3 中列表推导式只是一个给 list
类型的构造器提供生成器表达式的语法糖。
>>> list(x for x in 'Silly Walk') ['S', 'i', 'l', 'l', 'y', ' ', 'W', 'a', 'l', 'k'] >>> [x for x in 'Silly Walk'] ['S', 'i', 'l', 'l', 'y', ' ', 'W', 'a', 'l', 'k']
这也意味着循环变量不再会掺入附近的命名空间了。
生成器推导式也能够用 Python 2.6 及其之后版本的 dict()
和 set()
构造器生成。可是在 Python 3 还有 Python 2.7 中,你能够用新的语法来定义字典和列表推导式:
>>> department = 'Silly Walk' >>> {x: department.count(x) for x in department} {'a': 1, ' ': 1, 'i': 1, 'k': 1, 'l': 3, 'S': 1, 'W': 1, 'y': 1} >>> {x for x in department} {'a', ' ', 'i', 'k', 'l', 'S', 'W', 'y'}
还有许多新的模块值得你一看。在这里我就很少说了,由于大多数若是你不重写软件的话可能获益很少,但你应该知道它们存在。你能够翻看一下 Python 文档来了解一下。
abc
abc
模块包含了对生成抽象的基础类的支持,你能够 标记 一个基础类的方法或者属性为“抽象”,意思是你必须在子类中进行实现,不然没法实例化。
抽象基础类也能够建立没有实体方法的类,用于定义接口。
abc
模块在 Python 2.6 及其之后的版本被支持。
multiprocessing
和 future
multiprocessing
是一个新的模块,用于进行多进程操做,它容许你拥有进程队列和使用锁,还有用于同步进程的 信号标 。
multiprocessing
在 Python 2.6 之后被加入支持。在 2.4 和 2.5 你可使用 CheeseShop 。
若是你要作并发你能够看一下 future
模块,在 Python 3.2 引入了这个模块,在 Python 2.5 及之后的版本能够用 参考这里 。
numbers
和 fractions
Python 3 加入了这个库。大多数状况下你不会注意到它,可是颇有趣的是 fractions
模块,在 Python 2.6 被支持。
>>> from fractions import Fraction >>> Fraction(3,4) / Fraction('2/3') Fraction(9, 8)
还有 numbers
模块,包含支持全部数字类型的抽象基础类。若是你正在实现你本身的数字类型的话,那么它很是有用。
生成器推导式 - generator comprehension
列表推导式 - list comprehension
生成器 - generator
抽象的基础类 - abstract base classes
在湖闻樟注: