====== 16、Python 版本2与版本3的区别 ====== 上次,我说这期将会继续讲解pygame,但由于不久前我向某人承诺讨论 Python 2.x 和 3.x 之间的区别,并且我不想食言,所以下次我们再深入钻研pygame。 Python 3.x 有很大改变。网上有大量关于这些改变的资料,我会在这篇文章的末尾提供几个链接。同样,对于这些改变的关注也有很多,不过,这次我将会主要讲解那些对你目前所学的知识有所影响的改变。 那我们现在开始吧! ===== PRINT ===== 正如我之前所说,处理Print命令是最重要的改变之一。在2.x的版本中,我们可以简单的使用如下的命令完成打印功能: print “This is a test” 然而在3.x中,如果我们这样尝试,则会得到如下的错误提示: >>> print "This is a test" File "", line 1 print "This is a test" ^ SyntaxError: invalid syntax >>> 真是令人沮丧,如果要使用print命令,我们必须将所希望打印的内容放在一对括号之间,如下: print(“this is a test”) 这并不是一个很大的改变,但我们还是必须注意。你要准备替换一些在Python 2.x下可以运用的语法。 ===== 字符串格式化与变量替换 ===== 字符串格式化与变量替换同样被修改了,在2.x中,我们会编写如下的代码 >>> months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] >>> print "You selected month %s" % months[3] You selected month Apr >>> 如果在3.1中这么写,虽然你的确可以得到正确的结果,但是要注意"%s"和"%d"这样的格式化功能将要被淘汰了。新的方法是使用'{x}'这样的替换语句。 >>> months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] >>> print("You selected month {0}".format(months[3])) You selected month Apr >>> 在我看来这样的方式更利于阅读。你也可以像如下这样执行: >>> print("Hello {0}. I'm glad you are here at {1}".format("Fred","MySite.com")) Hello Fred. I'm glad you are here at MySite.com >>> 记住,你依然可以使用形如'%s'的语句,但他们将要被淘汰了。 ===== 数字 ===== 在Python 2.x中,如果你执行了如下的代码 x = 5/2.0 x的值将会是2.5, 然而,如果你这么写: x = 5/2 由于小数部分被截断,x将会是2。 在3.x中,如果这么写: x = 5/2 你依然可以得到2.5, 如果希望像以前一样截断小数的话,你需要采取如下的方法 x = 5//2 ===== 输入 ===== 不久前,我们曾经设计过一个目录系统,它使用了 raw_input() 来获取用户的反馈。 它是一个类似下面这样的语句: response = raw_input('Enter a selection -> ') 在2.x下,一切正常,然而, 在3.x下,我们会得到这样的错误: Traceback (most recent call last): File "", line 1, in NameError: name 'raw_input' is not defined 这不是什么大问题,由于 raw_input() 方法被 input() 所替代了,所以我们只需要把语句改为: response = input('Enter a selection -> ') 这样一来就行了。 ===== 不等于 ===== 在2.x的时代,我们可以用"<>"运算符来测试是否“不相等”, 然而,这个运算符在3.x中将不再合法,正确的做法是使用"!="运算符。 ===== 将老程序转换为3.x版本 ===== 3.x在发布时提供了一个帮助我们将2.x的程序代码转换为兼容3.x的工具。虽然这个工具并不总是有效的,但是在大多数情况下,它可以近乎完成我们的任务。 这个工具被(非常适当的)命名为 "2to3"。 让我们用个非常简单的小程序作为例子。这个程序要追溯到第三期上的教程。 #pprint1.py #Example of semi-useful functions def TopOrBottom(character,width): # width is total width of returned line return '%s%s%s' % ('+',(character * (width-2)),'+') def Fmt(val1,leftbit,val2,rightbit): # prints two values padded with spaces # val1 is thing to print on left, val2 is thing to print on right # leftbit is width of left portion, rightbit is width of right portion part2 = '%.2f' % val2 return '%s%s%s%s' % ('| ',val1.ljust(leftbit-2,' '),part2.rjust(rightbit-2,' '),' |') # Define the prices of each item item1 = 3.00 item2 = 15.00 # Now print everything out... print TopOrBottom('=',40) print Fmt('Item 1',30,item1,10) print Fmt('Item 2',30,item2,10) print TopOrBottom('-',40) print Fmt('Total',30,item1+item2,10) print TopOrBottom('=',40) 当在2.x环境中运行时,输出如下: +======================================+ | Item 1 3.00 | | Item 2 15.00 | +--------------------------------------+ | Total 18.00 | +======================================+ Script terminated. 当然,它无法在3.x的环境中运行 File "pprint1.py", line 18 print TopOrBottom('=',40) ^ SyntaxError: invalid syntax 让我们试着用转换工具来帮助我们解决这个问题。首先,我们应当备份想转换的文件。我会创建一个文件的副本,并在文件名的末尾加上“v3” cp pprint1.py pprint1v3.py 运行转换工具的方法有很多,最简单的方法就是直接让这个程序检测我们的代码并告诉我们问题在哪? > 2to3 pprint1v3.py RefactoringTool: Skipping implicit fixer: buffer RefactoringTool: Skipping implicit fixer: idioms RefactoringTool: Skipping implicit fixer: set_literal RefactoringTool: Skipping implicit fixer: ws_comma RefactoringTool: Refactored pprint1v3.py --- pprint1v3.py (original) +++ pprint1v3.py (refactored) @@ -15,9 +15,9 @@ item1 = 3.00 item2 = 15.00 # Now print everything out... -print TopOrBottom('=',40) -print Fmt('Item 1',30,item1,10) -print Fmt('Item 2',30,item2,10) -print TopOrBottom('-',40) -print Fmt('Total',30,item1+item2,10) -print TopOrBottom('=',40) +print(TopOrBottom('=',40)) +print(Fmt('Item 1',30,item1,10)) +print(Fmt('Item 2',30,item2,10)) +print(TopOrBottom('-',40)) +print(Fmt('Total',30,item1+item2,10)) +print(TopOrBottom('=',40)) RefactoringTool: Files that need to be modified: RefactoringTool: pprint1v3.py 注意,原始的代码并没有被改变,如果我们想让它自动改写我们的代码的话,我们得加上"-w" 标志。 > 2to3 -w pprint1v3.py RefactoringTool: Skipping implicit fixer: buffer RefactoringTool: Skipping implicit fixer: idioms RefactoringTool: Skipping implicit fixer: set_literal RefactoringTool: Skipping implicit fixer: ws_comma RefactoringTool: Refactored pprint1v3.py --- pprint1v3.py (original) +++ pprint1v3.py (refactored) @@ -15,9 +15,9 @@ item1 = 3.00 item2 = 15.00 # Now print everything out... -print TopOrBottom('=',40) -print Fmt('Item 1',30,item1,10) -print Fmt('Item 2',30,item2,10) -print TopOrBottom('-',40) -print Fmt('Total',30,item1+item2,10) -print TopOrBottom('=',40) +print(TopOrBottom('=',40)) +print(Fmt('Item 1',30,item1,10)) +print(Fmt('Item 2',30,item2,10)) +print(TopOrBottom('-',40)) +print(Fmt('Total',30,item1+item2,10)) +print(TopOrBottom('=',40)) RefactoringTool: Files that were modified: RefactoringTool: pprint1v3.py 注意,输出和上次的一样,但是这次我们的代码被转换成了一个3.x兼容的版本。 它现在看上去是这样: #pprint1.py #Example of semi-useful functions def TopOrBottom(character,width): # width is total width of returned line return '%s%s%s' % ('+',(character * (width-2)),'+') def Fmt(val1,leftbit,val2,rightbit): # prints two values padded with spaces # val1 is thing to print on left, val2 is thing to print on right # leftbit is width of left portion, rightbit is width of right portion part2 = '%.2f' % val2 return '%s%s%s%s' % ('| ',val1.ljust(leftbit-2,' '),part2.rjust(rightbit-2,' '),' |') # Define the prices of each item item1 = 3.00 item2 = 15.00 # Now print everything out... print(TopOrBottom('=',40)) print(Fmt('Item 1',30,item1,10)) print(Fmt('Item 2',30,item2,10)) print(TopOrBottom('-',40)) print(Fmt('Total',30,item1+item2,10)) print(TopOrBottom('=',40)) 现在这个程序可以在3.x环境中运行了,并且,它非常简单,依然可以在2.x环境中运行。 ==== 我是否需要现在就转而使用3.x版本呢? ==== 和任何编程语言被改动时所带来的问题一样:每次版本升级都带来了大量的语法变动,诸如 += 和 -= 的快捷方式令人意想不到,并且让我们更轻松。 ==== 如果现在就迁移到3.x版本,会有什么弊端么? ==== 当然,会有一些的。许多我们曾经使用过的库和模块目前都没办法在3.x版本中使用,例如我们在之前的教程中所使用的 Mutegen。 虽然这的确是个很大的阻碍,但它也不至于令你完全放弃 Python 3.x。 我的建议是从现在开始就使用正统的3.x语法来进行编程。Python 2.6 版本支持几乎所有你将会使用到的3.x的特性,这样一来,一旦哪天你真正切换到了3.x版本,一切都会十分自然。如果你只需要使用标准模块,那就动手升级吧,否则,你最好还是等等那些模块支持3.x版本。 下面是一些我认为或许对你有所帮助的链接,第一个是2to3工具的使用说明,第二个是一个很不错的4页长的参考手册,第三个是一本关于如何使用Python的书,我认为它是目前所有同类题材中写的最好的。 ===== 参考 ===== * [[http://docs.python.org/library/2to3.html|2to3 usage ]] * [[http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf|Moving from Python 2 to Python 3 (A 4 page cheat sheet)]] * [[http://diveintopython3.org/ |Dive into Python 3]]