DAY 136 python2和python3的差异

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,而加上前缀bb'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中如果没有声明,那么除法默认的是截断式除法,如:

DAY 136 python2和python3的差异
(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
DAY 136 python2和python3的差异

当然,如果这个时候你想要使用截断式除法,为:

>>> 3//4
0

 

3.print_function

from __future__ import print_function

即在python2中使用python3的print函数

DAY 136 python2和python3的差异
>>> 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
DAY 136 python2和python3的差异

可见导入了后,使用python2的print则会报错

小结

由于Python是由社区推动的开源并且免费的开发语言,不受商业公司控制,因此,Python的改进往往比较激进,不兼容的情况时有发生。Python为了确保你能顺利过渡到新版本,特别提供了__future__模块,让你在旧的版本中试验新版本的一些特性。

上一篇:Java07-1_Java流程控制---用户交互Scanner


下一篇:【Linux】Ubuntu20.04同时安装python3和python2