python3引入了一系列向后不兼容的变更。大多数不兼容的地方主要是:移除二义性和错误修正。
1.字符串类型
python中有两种字符类型:字节字符串和文本字符串。
版本 python2 python3
字节字符串 str bytes
文本字符串 Unicode str
2.默认字符
python2中默认的字符串类型默认是ASCII,python3中默认的字符串类型是Unicode。
3.print
python2中,print是个特殊语句,python3中print是函数。
python2:print 'hello word!'
python3:print('hello word!',file=sys.stderr)
4.除法/
python2中/的结果是整型,python3中是浮点类型。
5.导入
python2中的包导入顺序:标准库—相对倒入(即当前目录)—绝对导入(sys.path)
python3中的包导入顺序:标准库—绝对导入(如果想要相对导入,使用from .moudel)
6.类
python2中默认类是旧式类,需要显式继承新式类(object)来创建新式类。
python3中完全移除旧式类,所有类都是新式类,但仍可显式继承object类。
7.元类声明
python2中声明元类:__metaclass__ = MetaClass
python3中声明元类:class newclass(metaclass=MetaClass):pass
8.异常
python2中引发异常:raise ValueError,'Invalid value'
python3中引发异常:raise ValueError('Invalid value')——在python2中也生效
9.处理异常
python2中处理异常:
try:
raise ValueError,'Invalid value'
except ValueError,e:
pass
python3中处理异常:
try:
raise ValueError,'Invalid value'
except ValueError as e: #在python2中也生效
pass
python2中异常链会丢失原始异常信息,即:处理B异常时引发了A异常,B异常信息会丢失。
python3中将原始异常信息赋值给__context__属性。并且可以显式指定一个异常作为另一个异常的子句:raise DatabaseError() from IOError()
10.字典
python2中的dict类中的keys、values和items均返回list对象,iterkeys、itervalues和iteritems返回生成器对象。
python3中移除了list、只返回一个生成器的对象,只保留视图(生成器),但方法名为:keys、values和items。
11.模块合并
python2中的StringIO和cStringIO合并为python3中的io
python2中的pickle和cPickle合并为python3中的pickle。
python2中的urllib、urllib2和urlparse合并为python3中的urllib
12.重命名模块
python3 python2
Configparser ConfigParser
filter itertools.ifilter
input raw_input
map itertools.imap
range xrange
functools.reduce reduce
socketserver SocketServer
zip itertools.izip
13.其他
Python的每个新版本都会增加一些新的功能,或者对原来的功能作一些改动。有些改动是不兼容旧版本的,也就是在当前版本运行正常的代码,到下一个版本运行就可能不正常了。
从Python 2.7到Python 3.x就有不兼容的一些改动,比如2.x里的字符串用'xxx'
表示str,Unicode字符串用u'xxx'
表示unicode,而在3.x中,所有字符串都被视为unicode,因此,写u'xxx'
和'xxx'
是完全一致的,而在2.x中以'xxx'
表示的str就必须写成b'xxx'
,以此表示“二进制字符串”。
要直接把代码升级到3.x是比较冒进的,因为有大量的改动需要测试。相反,可以在2.7版本中先在一部分代码中测试一些3.x的特性,如果没有问题,再移植到3.x不迟。
Python提供了__future__
模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。举例说明如下:
为了适应Python 3.x的新的字符串的表示方法,在2.7版本的代码中,可以通过unicode_literals
来使用Python 3.x的新的语法:
# still running on Python 2.7
from __future__ import unicode_literals
print '\'xxx\' is unicode?', isinstance('xxx', unicode)
print 'u\'xxx\' is unicode?', isinstance(u'xxx', unicode)
print '\'xxx\' is str?', isinstance('xxx', str)
print 'b\'xxx\' is str?', isinstance(b'xxx', str)
注意到上面的代码仍然在Python 2.7下运行,但结果显示去掉前缀u
的'a string'
仍是一个unicode,而加上前缀b
的b'a string'
才变成了str:
$ python task.py
'xxx' is unicode? True
u'xxx' is unicode? True
'xxx' is str? False
b'xxx' is str? True
类似的情况还有除法运算。在Python 2.x中,对于除法有两种情况,如果是整数相除,结果仍是整数,余数会被扔掉,这种除法叫“地板除”:
>>> 10 / 3
3
要做精确除法,必须把其中一个数变成浮点数:
>>> 10.0 / 3
3.3333333333333335
而在Python 3.x中,所有的除法都是精确除法,地板除用//
表示:
$ python3
Python 3.3.2 (default, Jan 22 2014, 09:54:40)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
如果你想在Python 2.7的代码中直接使用Python 3.x的除法,可以通过__future__
模块的division
实现:
from __future__ import division
print '10 / 3 =', 10 / 3
print '10.0 / 3 =', 10.0 / 3
print '10 // 3 =', 10 // 3
结果如下:
10 / 3 = 3.33333333333
10.0 / 3 = 3.33333333333
10 // 3 = 3
__future__是python2的概念,其实是为了使用python2时能够去调用一些在python3中实现的特性
1.absolute_import
from __future__ import absolute_import
这是一个在py2.x中导入3.x的导入特性的语句, 是为了区分出绝对导入和相对导入
声明为绝对引用。因为在Python 2.4或之前默认是相对引用,即先在本目录下寻找模块。但是如果本目录中有模块名与系统(sys.path)模块同名冲突,而想要引用的是系统模块时,该声明就能够起作用了。这样你调用import string时引入的就是系统的标准string.py,调用from pkg import string来引入当前目录的string.py
⚠️但是其实最好是不要声明与系统模块同名的模块,如果实在需要同名,最好使用from XXX import XXX来导入
2.division
from __future__ import division
在python3中默认是精确除法,而python2中默认的是截断式除法,如果在python2想要使用精确除法,就使用这个语句来声明
在python2中如果没有声明,那么除法默认的是截断式除法,如:
(deeplearning2) userdeMBP:~ user$ python Python 2.7.15 |Anaconda, Inc.| (default, Dec 14 2018, 13:10:39) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 3/4 0 >>> from __future__ import division >>> 3/4 0.75
当然,如果这个时候你想要使用截断式除法,为:
>>> 3//4 0
3.print_function
from __future__ import print_function
即在python2中使用python3的print函数
>>> print 'now in python2 it is right' now in python2 it is right >>> print('now in python2 it is right too') now in python2 it is right too >>> from __future__ import print_function >>> print 'now in python2 it is wrong' File "<stdin>", line 1 print 'now in python2 it is wrong' ^ SyntaxError: invalid syntax >>> print('now in python2 it is right') now in python2 it is right
可见导入了后,使用python2的print则会报错
小结
由于Python是由社区推动的开源并且免费的开发语言,不受商业公司控制,因此,Python的改进往往比较激进,不兼容的情况时有发生。Python为了确保你能顺利过渡到新版本,特别提供了__future__
模块,让你在旧的版本中试验新版本的一些特性。