笔者最近将一个在Python 2.7.5上运行得很顺利的源代码,放到Python 3.4.4上运行,
出现一些错误,一一总结分析,以飨读者。
1. 除法运算中商的默认类型的改变。
在Python 2中,如果被除数和除数都是整数,那么商默认类型是整数(int),即使商是小数,输出也是取整后的值。如果要想获得小数,那么除数或者被除数之一需要写出浮点数的形式。
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information.
>>> 7/2
3
>>> 7/2.0
3.5
>>> 7.0/2
3.5
在Python 3中,除法运算中商的默认类型的改变了,即无论被除数和除数的形式,商的默认类型是浮点数(float)。这一点回归到人们日常生活的方式。
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information.
>>> 7/2
3.5
>>> 4/2
2.0
上述改变在一些具体应用场合会引起错误,在Python3.4中:
>>> Num = 7/2
>>> [3]*Num
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
[3]*Num
TypeError: can't multiply sequence by non-int of type 'float'
2. dict_keys,dict_values类的出现。
在Python 2中,一个字典的所有键构成一个列表(List),所有的值构成一个列表(List)。
例如:给定一个关于水果和单价(元/斤)的fruit_dict字典。在Python 2.7.5中:
>>> fruit_dict
{'grape': 27.0, 'apple': 5.66, 'mango': 10.6, 'watermelon': 5.38, 'orange': 5.9, 'Cherry_Chili': 45.8}
>>> fruit_dict.keys()
['grape', 'apple', 'mango', 'watermelon', 'orange', 'Cherry_Chili']
>>> type(fruit_dict.keys())
<type 'list'>
在Python 3中,一个字典的所有键构成一个字典键类(dict_keys),所有的值构成一个字典值类(dict_values)。在Python 3.4.4中:
>>> fruit_dict.keys()
dict_keys(['grape', 'apple', 'mango', 'watermelon', 'orange', 'Cherry_Chili'])
>>> type(fruit_dict.keys())
<class 'dict_keys'>
在Python 3.4中运行如下程序:
>>> for fruit in fruit_dict.keys():
if fruit_dict[fruit] > 10:
del fruit_dict[fruit]
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
for fruit in fruit_dict.keys():
RuntimeError: dictionary changed size during iteration
如何解决这个问题呢?只需将dict_keys转化成列表即可。
>>> for fruit in list(fruit_dict.keys()):
if fruit_dict[fruit] > 10:
del fruit_dict[fruit]
3. range类的出现,取消xrange类型。
在Python 2中,一个range()函数能直接生成一个列表类型(List type)。例如:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
为了在生成大的列表时,避免占用大的内存空间,Python 2中有一个xrange()函数,输出是xrange类型。
>>> x = xrange(100000)
>>> x
xrange(100000)
>>> type(x)
<type 'xrange'>
在Python3中,一个range()函数生成的是一个range类(range class)。由此,取消了Python 2中的xrange()函数。
>>> x = range(10)
>>> x
range(0,10)
>>> type(x)
<class ‘range’>
List类型有:.append(), .count(),.extend(),.index(),.insert(),.pop(),.remove(),.reverse(),.sort() 等9种操作;range类有:.count(),.index(),.start,.stop,.step等5种操作。两种仅有2种操作可以共用,所以,在Python 3中,
>>> x
Range(0,10)
>>> x.reverse()
Traceback (most recent call last):
File “<pyshell#43>”, line 1, in <module>
x.reverse()
AttributeError: ‘range’ object has no attribute ‘reverse’
解决方法,将’range’ class转化成 list再做处理。
小结:
基于个人应用经验和Python的官方立场,笔者个人认为应该过渡到Python 3上来,即使我们可能对Python2已经非常熟悉。从Python 2到Python3,如果是小段的源代码,可以通过自己一步一步的解决,对于大量的源代码,可以通过2to3这个工具来处理大部分内容,如果有特殊需要将Python3的源代码转换成Python2的代码,可以使用3to2这个工具。后面再分享这方面的使用情况。