真格量化即将上线对Python3的支持。






由于版本间的差异,Python开发者经常需要解决不同版本的兼容问题,除了大家都知道的print是否需要括号,我们来看看还有哪些兼容不同版本的方法和语法差异的注意事项:


一,使用ImportError


Python3中将一些Python2的模块名称做了修改,需要我们做一些处理来保证代码在不同Python版本中能够正常运行。


# -*- coding: utf-8 -*-

 

try:

    # Python3

    from configparser import ConfigParser

except ImportError:

    # Python2

    from ConfigParser import ConfigParser

 

config = ConfigParser()

 

# do something


urllib库也是不兼容Python2和Python3的


# -*- coding: utf-8 -*-

 

try:

    # Python2

    from urllib import urlencode  

    from urllib import quote

    from urlparse import urlparse

    import urllib2 as request

except ImportError:

    # Python3

    from urllib.parse import urlencode  

    from urllib.parse import quote

    from urllib.parse import urlparse

    import urllib.request as request

 

# do something


二,根据版本来判断

根据sys.version_info.major来判断Python的版本,根据不同的版本导入不同的库。


# -*- coding: utf-8 -*-

import sys

 

if sys.version_info.major == 2:

    # Python2

    from urllib import urlencode

    from urllib import quote

    from urlparse import urlparse

    import urllib2 as request

else:

    # Python3

    from urllib.parse import urlencode  

    from urllib.parse import quote

    from urllib.parse import urlparse

    import urllib.request as request

# do something



三、使用脚本将py2代码转为py3


使用命令2to3 -w file.py可以直接在原地修改文件。其他命令可以使用2to3 --help查看;2to3 file.py可以看到转变前后的内容对比

2to3是Python自带的一个代码转换工具,可以将python2的代码自动转换为python3的代码。当然,不幸的是转换出的代码并没有对Python2的兼容做任何的处理。所以我们并不真正使用2to3转换出的代码。不过我们可以执行 2to3 file.py 查看输出信息,并修正相关问题。


四、使用python -3执行Python程序


2to3 可以检查出很多Python2&3的兼容性问题,但也有很多问题是2to3发现不了的。在加上 -3 参数后,程序在运行时会在控制台上将Python2和Python3不一致,同时2to3无法处理的问题提示出来。比如Python3和Python2中对除法的处理规则做过改变。使用-3参数执行4/2将提示 DeprecationWarning: classic int division 。

python -3 file.py


五、使用__future__导入


使用Python3的print函数,禁用Python2的print语句:from __future__ import print_function

像Python3一样,int除以int得float,而不像Python2那样是整除:from __future__ import division  

像Python3一样,字符串字面量的类型为文本(Python2中的unicode,Python3中的str),而不是字节(Python2中的str,Python3中的bytes)

from __future__ import unicode_literal


 

Python2和Python3的print也有不同。print在Python2中是个关键字,而在Python3中是个函数。


在Python2中:


在Python3中:


还有:


六、注意列表推导式的变量作用域


在Python2中,列表推导式中的索引变量的是可以泄露到其封闭作用域中的。而Python3中则不可以。

 
下面举一个简单的例子说明这个问题,如我们在一个for循环内部使用列表推导式:

for i in range(2):
    a = [i for i in range(5)]
    print(i)



在Python3中,上面的代码输出为

>>0
>>1

而在Python2中,上面的代码输出为

>>4
>>4


七,除法的区别


Python中除法有两种运算符:’/’和’//’;有三种类型的除法:传统除法、Floor除法和真除法。  


X / Y类型:

在Python2.6或者之前,这个操作对于整数运算会省去小数部分,而对于浮点数运算会保持小数部分;在Python3.0中变成真除法(无论任何类型都会保持小数部分,即使整除也会表示为浮点数形式)。

示例代码:
>>>3//2
1
>>>3//2.0
1.0
>>>4//2
2
>>>4//2.0
2.0


Python 3.4版本中结果:

>>>3/2
1.5
>>>3/2.0
1.5
>>>4/2
2.0
>>>4/2.0
2.0



X // Y 类型

Floor除法:在Python 2.2中新增的操作,在Python2.6和Python3.0中均能使用,这个操作不考虑操作对象的类型,总是省略小数部分,剩下最小的能整除的整数部分。

示例代码:

Python 2.7版本中结果:
>>>3//2
1
>>>3//2.0
1.0
>>>4//2
2
>>>4//2.0
2.0

Python 3.4版本中结果(与2.7版本一样):

>>>3//2
1
>>>3//2.0
1.0
>>>4//2
2
>>>4//2.0
2.0


概括来讲:在Python 2.6中,’/’执行传统除法,如果操作数都是整数的话,执行截断的整数除法(即对于结果只保留整数部分),否则,执行浮点除法(保留余数);’//’执行Floor除法,与Python3.0一样,对于整数执行截断除法,浮点数执行浮点除法。在Python 3.0中,’/’总是执行真除法,不管操作数的类型,都会返回包含任何余数的浮点结果;’//’执行Floor除法,截除掉余数并且针对整数操作数返回一个整数,如果有任何一个操作数是浮点数,则返回一个浮点数。

 

八,Unicode

 

Python 2有两种字符串类型:strunicodePython 3中的字符串默认就是UnicodePython 3中的str相当于Python 2中的unicode

Python 2中,如果代码中包含非英文字符,需要在代码文件的最开始声明编码,如下

# -*- coding: utf-8 -*-

Python 3中,默认的字符串就是Unicode,就省去了这个麻烦,下面的代码在Python 3可以正常地运行

a = "汉字"

print(a)

 

九,has_key

 

Python 3中的字典不再支持has_key方法

Python 2

person = {"age": 30, "name": "Xiao Wang"}

print "person has key \"age\": ", person.has_key("age")

print "person has key \"age\": ", "age" in person

输出

person has key "age":  True

person has key "age":  True

 

Python 3

person = {"age": 30, "name": "Xiao Wang"}

print("person has key \"age\": ", "age" in person)

输出

person has key "age":  True

 

print("person has key \"age\": ", person.has_key("age"))

输出

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: 'dict' object has no attribute 'has_key'

 

十 异常处理

 

Python 2中捕获异常一般用下面的语法

try:

    1/0

except ZeroDivisionError, e:

    print str(e)

或者

try:

    1/0

except ZeroDivisionError as e:

    print str(e)

Python 3中不再支持前一种语法,必须使用as关键字。

 

十一  xrange

 

Python 2中有 range xrange 两个方法。其区别在于,range返回一个list,在被调用的时候即返回整个序列;

xrange返回一个iterator,在每次循环中生成序列的下一个数字。

 

Python 3中不再支持 xrange 方法,Python 3中的 range 方法就相当于 Python 2中的 xrange 方法。

 

十二 map函数

Python 2中,map函数返回list,而在Python 3中,map函数返回iterator

Python 2

map(lambda x: x+1, range(5))

输出

[1, 2, 3, 4, 5]



Python 3

map(lambda x: x+1, range(5))

输出

<map object at 0x7ff5b103d2b0>



list(map(lambda x: x+1, range(5)))

输出

[1, 2, 3, 4, 5]

filter函数在Python 2Python 3中也是同样的区别。