13.1 语言和标准库

这门语言并没有彻底地修改。我敢肯定你已经简单看过了。本书不会包含全部的修改清单,那太无趣了,而且可以在网上找到。Porting to Python 3http://python3porting.com/)这本书给出了要支持Python 3所需做修改的良好概述。

如果你还没来得及看一下Pyton 3所做的语言修改,建议看一下。这是一门非常好的语言,少了很多生僻的场景,针对不同对象基类有了更加清晰的接口。你会喜欢Python 3的。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

但它也带来了巨大的兼容性问题。某些语句的语法变化(如异常捕获)已经完全去除了对旧的Python版本的兼容性,而且如果使用的话,处理起来会非常痛苦。在1.4节中讨论的hacking工具能帮你解决这些不兼容的用法,并避免引入更多。

支持Python的多版本时,应该尽量避免同时支持Python 3.3和早于Python 2.6的版本。Python 2.6是第一个为向Python 3移植提供足够兼容性的版本。

影响你最多的可能是字符串处理方面。在Python 3中过去称为unicode,现在叫str(如图13-1和图13-2所示)。这意味着任何字符串都是Unicode的,也就是说u'foobar''foobar'是同一样东西2

阅读 ‧ 电子书库

图13-1 Python 2基类

阅读 ‧ 电子书库

图13-2 Python 3基类

实现unicode方法的类应该将其重命名为str,因为unicode方法将不再使用。可以通过一个类装饰器自动完成这个过程。

# -*- encoding: utf-8 -*-
import six

# This backports your Python 3__str__ for Python 2
def unicode_compat(klass):
  if not six.PY3:
    klass.__unicode__ = klass.__str__
    klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
  return klass

@unicode_compat
class Square(object):
  def __str__(self):
    return u"■ " + str(id(self))

这种方式可以针对所有返回Unicode的Python版本实现一个方法,装饰器会处理兼容性问题。

另一个处理Python和Unicode的技巧是使用unicode_literals,它从Python2.6开始提供3

>>> 'foobar'
'foobar'
>>> from __future__ import unicode_literals
>>> 'foobar'
u'foobar'

许多函数不再返回列表而是返回可迭代对象(如range)。此外,字典方法(如keys或者items)现在也返回可迭代对象,而函数iterkeysiteritems则已经被删除。这是一个巨大的变化,但six(将在13.3节中讨论)将帮你处理这个问题。

显然,标准库也经历了从Python 2到Python 3的演化,但无需过分担心。一些模块已经被重命名或者删除,但最终呈现的是更为清晰的布局。我不知道是否有官方的清单,但是http://docs.pythonsprints.com/python3_porting/py-porting.html就有一份很好的清单,或者也可以用搜索引擎找到。

six模块会在13.3节中讨论,它对于维护Python 2和3的兼容性很有用。