2.2 Python的两大版本
目前Python主要有两个大的版本:
Python 2
Python 3
Python两大版本的不同写法
关于两种版本的对比,也常写成为
Python 2.x VS Python 3.x
Python 2 VS Python 3
py2 VS py3
读者以后看到类似写法,明白其指的是Python 2和Python 3就可以了。
2.2.1 Python版本历史
为了更深入地理解Python 2和Python 3的区别,此处先简要介绍Python版本的发展历史。
Python从1989年诞生起到现在,按照主版本号的不同,主要有1、2和最新的3。下面介绍一下其中相对使用较广的几个版本。
1. Python 1.6
相对来说,最早的Python 1.x系列的版本中,使用得比较广泛的就是Python 1.6左右的版本了。
2. Python 2.7
截至笔者写稿的2014年,Python的2系列的版本中用得相对最广泛、最流行的版本要数Python 2.7.x系列的版本了。
很多操作系统和平台中,包括现在主流的Ubuntu,Mac OS等系统中预装的Python都是Python 2.7.x的版本。
3. Python 3.x
此处所说的Python 3.x主要指的是2014年前后,Python刚刚发展到的3系列的版本。从Python 2到Python 3是一个很大的变化。这些变化包括很多基本的元素、函数接口和定义、设计理念等方面。虽然,这些变化总的来说在向好的方向进化,但是由于Python 3的变化,导致和旧的Python 2不太兼容,而之前Python 2系列的版本使用得太广泛了,包括很多第三方的库函数都是Python 2版本的,从而导致对于第三方库函数来说,如果需要全部支持Python 3则需要很大的改动,涉及的代码工作量和测试工作很多,所以现在很多第三方库函数暂时没有支持Python 3,或者是对于Python 3的支持还不够稳定。
所以当前的结论是,虽然Python 3是以后的趋势,但是目前多数人还在继续使用Python 2。
2.2.2 Python 2和Python 3之间的区别
介绍了Python各版本的基本历史后,下面再来详细解释Python 2和Python 3的区别。
Python2和Python3在很多基本的、最常用的函数和接口方面都变了,所以也会导致一些问题。其中最典型的要数前面提到的print函数的语法错误了。
例2.1 Python 3中print出现语法错误
在安装了最新版本的Python 3后却参考并运行了他人Python 2的示例代码,其中有用到print函数,结果就会导致print函数的语法错误:“SyntaxError: invalid syntax”。
介绍一个真实的案例,之前遇到了某个Python初学者就出现了如图2-1所示的错误。
1. print函数的基本语法
为了更清楚地解释此问题,需要先解释一下print函数的基本语法:
Python 2: print函数不带括号
Python 3: print函数必须带括号
图2-1 Python 3中print出错
下面详细阐述:
(1)print中不带百分号格式化的
python 2
print "Pyhon 2 can use print string without ()";
python 3
print("Python3, print must use () to output string");
(2)print中带百分号格式化的
python 2
print "old %s version is %d, print no ()"%("Python", 2);
python 3
print("new %s version is %d, print must have ()"%("Python", 3));
2.官网中print的用法
关于更多的新旧版本中print的用法,此处再整理一些官网中的例子以供参考。
(1)末尾不换行
python 2
print x,
python 3
print(x, end=" ")
(2)输出空白行
python 2
print
python 3
print()
(3)重定向输出
python 2
print >>sys.stderr, "fatal error"
python 3
print("fatal error", file=sys.stderr)
(4)打印输出表达式
python 2
print (x, y)
python 3
print((x, y))
至此,读者对于Python 2和Python 3中的print的语法应该比较清楚了。
3. Python 3相比Python 2的其他变化
除了print之外,关于Python从2发展到3后其他的变化,虽然对于初学者来说暂时无需了解如此多的细节,不过为了知识的完整性,以及为今后遇到的问题提供参考,所以还是有必要在此处一并整理出一些大的语法方面的变化。
(1)部分返回值用view和Iterator取代了list
dict的有些方法不再返回list
以前dict的dict.keys()、dict.items()和dict.values()是返回list的,现在变为返回views。比如,以前用:
k = d.keys(); k.sort()
现在改用:
k = sorted(d)
去掉了dict的部分方法
去掉了dict的dict.iterkeys()、dict.iteritems()和dict.itervalues()。
map()和filter()返回迭代器了
range()变成以前的xrange()的效果了
所以去掉了xrange()。
zip()返回迭代器了
(2)带排序的比较
简化了带排序的比较
builtin.sorted()和list.sort()不再支持cmp作为参数,而改用key
取消了cmp()和_?_cmp_?_(),改用_?_lt_?_(),以及用带_?_hash_?_()的_?_eq_?_()实现更加复杂的比较
(3)整型变量
long改名为int
类似于“”这样的表达式返回float变量
去掉了sys.maxint
repr()返回的值不再包含L后缀
八进制数值,不再是0720的形式,而变成0o720
(4)Unicode和8位字节的区别变为文本和数据的区别
从之前的Unicode字符串(unicode)和8位的字符串(str)变为文本(str)和二进制的数据(bytes)。
不能再用u"...",且对于二进制数据用b"..."。
文本字符串和二进制数据之间不再支持混用,需要转换时,可以用对应的str.encode()和bytes.decode(),或者bytes(s, encoding=...)和str(b, encoding=...)。
反斜杠在原始字符串中就是字面意思,没有转义的含义。
举例说明:
1)Python 2.6中ur'\u20ac'表示单个的euro字符;
2)Python 3.0中r'\u20ac'表示对应的一个包含了6个字符的字符串。
去除了内置的抽象类型变量basestring而改用str。
打开文件后返回的是解码后的Unicode字符串,加上b前缀后返回的是字节数组,所以也无需再用之前的codecs模块了。
sys.stdin、sys.stdout和sys.stderr的初始值从io.TextIOBase改为仅支持Unicode字符串,如果想要这些字符流的字节数据,可以使用io.TextIOBase.buffer。
文件名当做参数传递进入和返回时也都是Unicode字符串。
部分系统相关的API,比如os.environ和sys.argv,当系统用默认编码无法解析相关的字节时,可能会存在一些问题。
字符串的repr()不再返回转义后的非ASCII字符,但仍会转义那些控制字符和非打印字符。
默认字符串编码为UTF-8。
非ASCII字符不允许用于标识符。
去掉了StringIO和cStringIO模块,改为先导入io模块后再引用对应的io.StringIO或io.BytesIO。