http://www.techug.com/the-difference-of-python2-and-python3#print
===================================================================
这个星期开始学习Python了,因为看的书都是基于Python2.x,而且我安装的是Python3.1,所以书上写的地方好多都不适用于Python3.1,特意在Google上search了一下3.x和2.x的区别。特此在自己的空间中记录一下,以备以后查找方便,也可以分享给想学习Python的friends.
1.性能 Py3.0运行 pystone benchmark的速度比Py2.5慢30%。Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可 以取得很好的优化结果。 Py3.1性能比Py2.5慢15%,还有很大的提升空间。 2.编码 Py3.X源码文件默认使用utf-8编码,这就使得以下代码是合法的: >>> 中国 = 'china' >>>print(中国) china 3. 语法 1)去除了<>,全部改用!= 2)去除``,全部改用repr() 3)关键词加入as 和with,还有True,False,None 4)整型除法返回浮点数,要得到整型结果,请使用// 5)加入nonlocal语句。使用noclocal x可以直接指派外围(非全局)变量 6)去除print语句,加入print()函数实现相同的功能。同样的还有 exec语句,已经改为exec()函数 例如: 2.X: print "The answer is", 2*2 3.X: print("The answer is", 2*2) 2.X: print x, # 使用逗号结尾禁止换行 3.X: print(x, end=" ") # 使用空格代替换行 2.X: print # 输出新行 3.X: print() # 输出新行 2.X: print >>sys.stderr, "fatal error" 3.X: print("fatal error", file=sys.stderr) 2.X: print (x, y) # 输出repr((x, y)) 3.X: print((x, y)) # 不同于print(x, y)! 7)改变了顺序操作符的行为,例如x<y,当x和y类型不匹配时抛出TypeError而不是返回随即的 bool值 8)输入函数改变了,删除了raw_input,用input代替: 2.X:guess = int(raw_input('Enter an integer : ')) # 读取键盘输入的方法 3.X:guess = int(input('Enter an integer : '))
9)去除元组参数解包。不能def(a, (b, c)):pass这样定义函数了 10)新式的8进制字变量,相应地修改了oct()函数。 2.X的方式如下: >>> 0666 438 >>> oct(438) '0666' 3.X这样: >>> 0666 SyntaxError: invalid token (<pyshell#63>, line 1) >>> 0o666 438 >>> oct(438) '0o666' 11)增加了 2进制字面量和bin()函数 >>> bin(438) '0b110110110' >>> _438 = '0b110110110' >>> _438 '0b110110110' 12)扩展的可迭代解包。在Py3.X 里,a, b, *rest = seq和 *rest, a = seq都是合法的,只要求两点:rest是list 对象和seq是可迭代的。 13)新的super(),可以不再给super()传参数, >>> class C(object): def __init__(self, a): print('C', a) >>> class D(C): def __init(self, a): super().__init__(a) # 无参数调用super() >>> D(8) C 8 <__main__.D object at 0x00D7ED90> 14)新的metaclass语法: class Foo(*bases, **kwds): pass 15)支持class decorator。用法与函数decorator一样: >>> def foo(cls_a): def print_func(self): print('Hello, world!') cls_a.print = print_func return cls_a >>> @foo class C(object): pass >>> C().print() Hello, world! class decorator可以用来玩玩狸猫换太子的大把戏。更多请参阅PEP 3129 4. 字符串和字节串 1)现在字符串只有str一种类型,但它跟2.x版本的unicode几乎一样。
2)关于字节串,请参阅“数据类型”的第2条目 5.数据类型 1)Py3.X去除了long类型,现在只有一种整型——int,但它的行为就像2.X版本的long 2)新增了bytes类型,对应于2.X版本的八位串,定义一个bytes字面量的方法如下: >>> b = b'china' >>> type(b) <type 'bytes'> str对象和bytes对象可以使用.encode() (str -> bytes) or .decode() (bytes -> str)方法相互转化。 >>> s = b.decode() >>> s 'china' >>> b1 = s.encode() >>> b1 b'china' 3)dict的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函数都被废弃。同时去掉的还有 dict.has_key(),用 in替代它吧 6.面向对象 1)引入抽象基类(Abstraact Base Classes,ABCs)。 2)容器类和迭代器类被ABCs化,所以cellections模块里的类型比Py2.5多了很多。 >>> import collections >>> print('\n'.join(dir(collections))) Callable Container Hashable ItemsView Iterable Iterator KeysView Mapping MappingView MutableMapping MutableSequence MutableSet NamedTuple Sequence Set Sized ValuesView __all__ __builtins__ __doc__ __file__ __name__ _abcoll _itemgetter _sys defaultdict deque 另外,数值类型也被ABCs化。关于这两点,请参阅 PEP 3119和PEP 3141。 3)迭代器的next()方法改名为__next__(),并增加内置函数next(),用以调用迭代器的__next__()方法 4)增加了@abstractmethod和 @abstractproperty两个 decorator,编写抽象方法(属性)更加方便。 7.异常 1)所以异常都从 BaseException继承,并删除了StardardError 2)去除了异常类的序列行为和.message属性 3)用 raise Exception(args)代替 raise Exception, args语法 4)捕获异常的语法改变,引入了as关键字来标识异常实例,在Py2.5中: >>> try: ... raise NotImplementedError('Error') ... except NotImplementedError, error:
... print error.message ... Error 在Py3.0中: >>> try: raise NotImplementedError('Error') except NotImplementedError as error: #注意这个 as print(str(error)) Error 5)异常链,因为__context__在3.0a1版本中没有实现 8.模块变动 1)移除了cPickle模块,可以使用pickle模块代替。最终我们将会有一个透明高效的模块。 2)移除了imageop模块 3)移除了 audiodev, Bastion, bsddb185, exceptions, linuxaudiodev, md5, MimeWriter, mimify, popen2, rexec, sets, sha, stringold, strop, sunaudiodev, timing和xmllib模块 4)移除了bsddb模块(单独发布,可以从获取) 5)移除了new模块 6)os.tmpnam()和os.tmpfile()函数被移动到tmpfile模块下 7)tokenize模块现在使用bytes工作。主要的入口点不再是generate_tokens,而是 tokenize.tokenize() 9.其它 1)xrange() 改名为range(),要想使用range()获得一个list,必须显式调用: >>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2)bytes对象不能hash,也不支持 b.lower()、b.strip()和b.split()方法,但对于后两者可以使用 b.strip(b’ \n\t\r \f’)和b.split(b’ ‘)来达到相同目的 3)zip()、map()和filter()都返回迭代器。而apply()、 callable()、coerce()、 execfile()、reduce()和reload ()函数都被去除了
现在可以使用hasattr()来替换 callable(). hasattr()的语法如:hasattr(string, '__name__')
4)string.letters和相关的.lowercase和.uppercase被去除,请改用string.ascii_letters 等 5)如果x < y的不能比较,抛出TypeError异常。2.x版本是返回伪随机布尔值的 6)__getslice__系列成员被废弃。a[i:j]根据上下文转换为a.__getitem__(slice(I, j))或 __setitem__和 __delitem__调用 7)file类被废弃,在Py2.5中: >>> file <type 'file'> 在Py3.X中: >>> file Traceback (most recent call last): File "<pyshell#120>", line 1, in <module> file NameError: name 'file' is not defined
=====================
Python2.4+ 与 Python3.0+ 主要变化或新增内容
Python2 Python3print是内置命令 print变为函数print >> f,x,y print(x,y,file=f)print x, print(x,end='')reload(M) imp.reload(M)apply(f, ps, ks) f(*ps, **ks)x <> y x != ylong int1234L 1234d.has_key(k) k in d 或 d.get(k) != None (has_key已死, in永生!!)raw_input() input()input() eval(input())xrange(a,b) range(a,b)file() open()x.next() x.__next__() 且由next()方法调用x.__getslice__() x.__getitem__()x.__setsilce__() x.__setitem__()__cmp__() 删除了__cmp__(),改用__lt__(),__gt__(),__eq__()等reduce() functools.reduce()exefile(filename) exec(open(filename).read())0567 0o567 (八进制) 新增nonlocal关键字 str用于Unicode文本,bytes用于二进制文本 新的迭代器方法range,map,zip等 新增集合解析与字典解析u'unicodestr' 'unicodestr'raise E,V raise E(V)except E , x: except E as x:file.xreadlines for line in file: (or X = iter(file))d.keys(),d.items(),etc list(d.keys()),list(d.items()),list(etc)map(),zip(),etc list(map()),list(zip()),list(etc)x=d.keys(); x.sort() sorted(d)x.__nonzero__() x.__bool__()x.__hex__,x.__bin__ x.__index__types.ListType list__metaclass__ = M class C(metaclass = M):__builtin__ builtinssys.exc_type,etc sys.exc_info()[0],sys.exc_info()[1],...function.func_code function.__code__ 增加Keyword-One参数 增加Ellipse对象 简化了super()方法语法用过-t,-tt控制缩进 混用空格与制表符视为错误from M import *可以 只能出现在文件的顶层出现在任何位置.class MyException: class MyException(Exception):thread,Queue模块 改名_thread,queuecPickle,SocketServer模块 改名_pickle,socketserverConfigSparser模块 改名configsparserTkinter模块 改名tkinter 其他模块整合到了如http模块,urllib, urllib2模块等os.popen subprocess.Popen基于字符串的异常 基于类的异常 新增类的property机制(类特性)未绑定方法 都是函数混合类型可比较排序 非数字混合类型比较发生错误/是传统除法 取消了传统除法, /变为真除法无函数注解 有函数注解 def f(a:100, b:str)->int 使用通过f.__annotation__ 新增环境管理器with/as Python3.1支持多个环境管理器项 with A() as a, B() as b 扩展的序列解包 a, *b = seq 统一所有类为新式类 增强__slot__类属性if X: 优先X.__len__() 优先X.__bool__()type(I)区分类和类型 不再区分(不再区分新式类与经典类,同时扩展了元类)静态方法需要self参数 静态方法根据声明直接使用无异常链 有异常链 raise exception from other_exception
因这学期负责Python课程的助教,刚开始上机试验的几节课,有很多同学用 Python3.4 的编译器编译 Python 2.7 的程序而导致不通过。Python 2.7.x 和 Python 3.x 版本并非完全兼容。
许多 Python 初学者想知道他们应该从 Python 的哪个版本开始学习。对于这个问题我的答案是 “你学习你喜欢的教程的版本,然后检查他们之间的不同。” 但如果你并未了解过两个版本之间的差异,个人推荐使用 Python 2.7.x 版本,毕竟大部分教材等资料还是用Python 2.7.x来写的。 但是如果你开始一个新项目,并且有选择权?我想说的是目前没有对错,只要你计划使用的库 Python 2.7.x 和 Python 3.x 双方都支持的话。尽管如此,当在编写它们中的任何一个的代码,或者是你计划移植你的项目的时候,是非常值得看看这两个主要流行的 Python 版本之间的差别的,以便避免常见的陷阱。 本文翻译自:__future__
模块
Python 3.x 介绍的 一些Python 2 不兼容的关键字和特性可以通过在 Python 2 的内置 __future__
模块导入。如果你计划让你的代码支持 Python 3.x,建议你使用 __future__
模块导入。例如,如果我想要 在Python 2 中表现 Python 3.x 中的整除,我们可以通过如下导入
1 | from __future__ import division |
更多的 __future__
模块可被导入的特性被列在下表中:
feature | optional in | mandatory in | effect |
---|---|---|---|
nested_scopes | 2.1.0b1 | 2.2 | : Statically Nested Scopes |
generators | 2.2.0a1 | 2.3 | : Simple Generators |
division | 2.2.0a2 | 3.0 | : Changing the Division Operator |
absolute_import | 2.5.0a1 | 3.0 | : Imports: Multi-Line and Absolute/Relative |
with_statement | 2.5.0a1 | 2.6 | : The “with” Statement |
print_function | 2.5.0a2 | 3.0 | : Make print a function |
unicode_literals | 2.5.0a2 | 3.0 | : Bytes literals in Python 3000 |
(Source: )
1 | from platform import python_version |
print
函数
很琐碎,而 print
语法的变化可能是最广为人知的了,但是仍值得一提的是: Python 2 的 print 声明已经被 print()
函数取代了,这意味着我们必须包装我们想打印在小括号中的对象。Python 2 不具有额外的小括号问题。但对比一下,如果我们按照 Python 2 的方式不使用小括号调用 print
函数,Python 3 将抛出一个语法异常(SyntaxError
)。
Python 2
1 2 3 4 | print 'Python', python_version() print 'Hello, World!' print( 'Hello, World!') print "text", ; print 'print more text on the same line' |
run result:
Python 2.7.6Hello, World!Hello, World!text print more text on the same linePython 3
1 2 3 4 | print( 'Python', python_version()) print( 'Hello, World!') print( "some text,", end="") print( ' print more text on the same line') |
run result:
Python 3.4.1Hello, World!some text, print more text on the same line 1 | print 'Hello, World!' |
run result:
File ““, line 1 print ‘Hello, World!’ ^SyntaxError: invalid syntaxNote:
以上通过 Python 2 使用Printing "Hello, World"
是非常正常的,尽管如此,如果你有多个对象在小括号中,我们将创建一个元组,因为 print
在 Python 2 中是一个声明,而不是一个函数调用。 1 2 3 | print 'Python', python_version() print( 'a', 'b') print 'a', 'b' |
run result:
Python 2.7.7(‘a’, ‘b’)a b整除
如果你正在移植代码,这个变化是特别危险的。或者你在 Python 2 上执行 Python 3 的代码。因为这个整除的变化表现在它会被忽视(即它不会抛出语法异常)。
因此,我还是倾向于使用一个float(3)/2
或 3/2.0
代替在我的 Python 3 脚本保存在 Python 2 中的 3/2
的一些麻烦(并且反而过来也一样,我建议在你的 Python 2 脚本中使用 from __future__ import division
) Python 2 1 2 3 4 5 | print 'Python', python_version() print '3 / 2 =', 3 / 2 print '3 // 2 =', 3 // 2 print '3 / 2.0 =', 3 / 2.0 print '3 // 2.0 =', 3 // 2.0 |
run result:
Python 2.7.63 / 2 = 13 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0Python 3
1 2 3 4 5 | print( 'Python', python_version()) print( '3 / 2 =', 3 / 2) print( '3 // 2 =', 3 // 2) print( '3 / 2.0 =', 3 / 2.0) print( '3 // 2.0 =', 3 // 2.0) |
run result:
Python 3.4.13 / 2 = 1.53 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0Unicode
Python 2 有 ASCII str() 类型,unicode()
是单独的,不是 byte
类型。 现在, 在 Python 3,我们最终有了 Unicode (utf-8)
字符串,以及一个字节类:byte
和 bytearrays
。
Python 2
1 | print 'Python', python_version() |
run result:
Python 2.7.6 1 | print type(unicode('this is like a python3 str type')) |
run result:
< type ‘unicode’ > 1 | print type(b'byte type does not exist') |
run result:
< type ‘str’ > 1 | print 'they are really' + b' the same' |
run result:
they are really the same 1 | print type(bytearray(b'bytearray oddly does exist though')) |
run result:
< type ‘bytearray’ >Python 3
1 2 | print( 'Python', python_version()) print( 'strings are now utf-8 \u03BCnico\u0394é!') |
run result:
Python 3.4.1strings are now utf-8 μnicoΔé! 1 2 | print( 'Python', python_version(), end="") print( ' has', type(b' bytes for storing data')) |
run result:
Python 3.4.1 has < class ‘bytes’ > 1 2 | print( 'and Python', python_version(), end="") print( ' also has', type(bytearray(b'bytearrays'))) |
run result:
and Python 3.4.1 also has < class ‘bytearray’> 1 | 'note that we cannot add a string' + b'bytes for data' |
run result:
-—————————————————————————————————————TypeError Traceback (most recent call last)< ipython-input-13-d3e8942ccf81> in < module>()——> 1 ‘note that we cannot add a string’ + b’bytes for data’TypeError: Can’t convert ‘bytes’ object to str implicitly
xrange
模块
在 Python 2 中 xrange()
创建迭代对象的用法是非常流行的。比如: for
循环或者是列表/集合/字典推导式。 这个表现十分像生成器(比如。“惰性求值”)。但是这个 xrange-iterable
是无穷的,意味着你可以无限遍历。 由于它的惰性求值,如果你不得仅仅不遍历它一次,xrange()
函数 比 range()
更快(比如 for
循环)。尽管如此,对比迭代一次,不建议你重复迭代多次,因为生成器每次都从头开始。 在 Python 3 中,range()
是像 xrange()
那样实现以至于一个专门的 xrange()
函数都不再存在(在 Python 3 中 xrange()
会抛出命名异常)。
1 2 3 4 5 6 7 8 | import timeit n = 10000 def test_range(n): return for i in range(n): pass def test_xrange(n): for i in xrange(n): pass |
Python 2
1 2 3 4 5 | print 'Python', python_version() print '\ntiming range()' %timeit test_range(n) print '\n\ntiming xrange()' %timeit test_xrange(n) |
run result:
Python 2.7.6timing range()
1000 loops, best of 3: 433 µs per looptiming xrange()
1000 loops, best of 3: 350 µs per loopPython 3
1 2 3 | print( 'Python', python_version()) print( '\ntiming range()') %timeit test_range(n) |
run result:
Python 3.4.1timing range()
1000 loops, best of 3: 520 µs per loop 1 | print(xrange( 10)) |
run result:
-—————————————————————————————————————NameError Traceback (most recent call last)in ()——> 1 print(xrange(10))
NameError: name ‘xrange’ is not defined
Python3中的range
对象的__contains__
方法
另外一件值得一提的事情就是在 Python 3 中 range
有一个新的 __contains__
方法(感谢 Yuchen Ying 指出了这个),__contains__
方法可以加速 “查找” 在 Python 3.x 中显著的整数和布尔类型。
1 2 3 4 5 6 7 8 9 10 | x = 10000000 def val_in_range(x, val): return val in range(x) def val_in_xrange(x, val): return val in xrange(x) print( 'Python', python_version()) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_range(x, x/ 2) %timeit val_in_range(x, x// 2) |
run result:
Python 3.4.11 loops, best of 3: 742 ms per loop1000000 loops, best of 3: 1.19 µs per loop 基于以上的 timeit 的结果,当它使一个整数类型,而不是浮点类型的时候,你可以看到执行查找的速度是 60000 倍快。尽管如此,因为 Python 2.x 的range
或者是 xrange
没有一个 __contains__
方法,这个整数类型或者是浮点类型的查询速度不会相差太大。 1 2 3 4 5 6 7 8 9 | print 'Python', python_version() assert(val_in_xrange(x, x/2.0) == True) assert(val_in_xrange(x, x/2) == True) assert(val_in_range(x, x/2) == True) assert(val_in_range(x, x//2) == True) %timeit val_in_xrange(x, x/ 2.0) %timeit val_in_xrange(x, x/ 2) %timeit val_in_range(x, x/ 2.0) %timeit val_in_range(x, x/ 2) |
run result:
Python 2.7.71 loops, best of 3: 285 ms per loop1 loops, best of 3: 179 ms per loop1 loops, best of 3: 658 ms per loop1 loops, best of 3: 556 ms per loop 下面说下__contain__
方法并没有加入到 Python 2.x 中的证据: 1 2 | print( 'Python', python_version()) range.__contains__ |
run result:
Python 3.4.1< slot wrapper ‘contains‘ of ‘range’ objects >
1 2 | print 'Python', python_version() range.__contains__ |
run result:
Python 2.7.7-—————————————————————————————————————
AttributeError Traceback (most recent call last)< ipython-input-7-05327350dafb> in < module>()1 print ‘Python’, pythonversion()——> 2 range.`_contains`AttributeError: ‘builtinfunctionor_method’ object has no attribute `’__contains‘`
1 2 | print 'Python', python_version() xrange.__contains__ |
run result:
Python 2.7.7-—————————————————————————————————————
AttributeError Traceback (most recent call last)< ipython-input-8-7d1a71bfee8e> in < module>()1 print ‘Python’, pythonversion()——> 2 xrange.`_contains`AttributeError: type object ‘xrange’ has no attribute '__contains__'
注意在 Python 2 和 Python 3 中速度的不同
有些人指出了 Python 3 的range()
和 Python 2 的 xrange()
之间的速度不同。因为他们是用相同的方法实现的,因此期望相同的速度。尽管如此,这事实在于 Python 3 倾向于比 Python 2 运行的慢一点。 1 2 3 4 5 | def test_while(): i = 0 while i < 20000: i += 1 return |
Python 3
1 2 | print( 'Python', python_version()) %timeit test_while() |
run result:
Python 3.4.1100 loops, best of 3: 2.68 ms per loopPython 2
1 2 | print 'Python', python_version() %timeit test_while() |
run result:
Python 2.7.61000 loops, best of 3: 1.72 ms per loopRaising exceptions
Python 2 接受新旧两种语法标记,在 Python 3 中如果我不用小括号把异常参数括起来就会阻塞(并且反过来引发一个语法异常)。
Python 2
1 | print 'Python', python_version() |
run result:
Python 2.7.6 1 | raise IOError, "file error" |
run result:
-—————————————————————————————————————
IOError Traceback (most recent call last)< ipython-input-8-25f049caebb0> in < module>()——> 1 raise IOError, “file error”IOError: file error
1 | raise IOError("file error") |
run result:
-—————————————————————————————————————IOError Traceback (most recent call last)< ipython-input-9-6f1c43f525b2> in < module>()——> 1 raise IOError(“file error”)IOError: file error
Python 3
1 | print 'Python', python_version() |
run result:
Python 3.4.1 1 | raise IOError, "file error" |
run result:
File ““, line 1
raise IOError, “file error” ^SyntaxError: invalid syntax 在 Python 3 中,可以这样抛出异常: 1 2 | print( 'Python', python_version()) raise IOError("file error") |
run result:
Python 3.4.1-—————————————————————————————————————
OSError Traceback (most recent call last)< ipython-input-11-c350544d15da> in < module>()1 print(‘Python’, python_version())——> 2 raise IOError(“file error”)OSError: file error
Handling exceptions
在 Python 3 中处理异常也轻微的改变了,在 Python 3 中我们现在使用 as
作为关键词。
Python 2
1 2 3 4 5 | print 'Python', python_version() try: let_us_cause_a_NameError except NameError, err: print err, '--> our error message' |
run result:
Python 2.7.6name ‘let_us_cause_a_NameError’ is not defined —> our error messagePython 3
1 2 3 4 5 | print( 'Python', python_version()) try: let_us_cause_a_NameError except NameError as err: print(err, '--> our error message') |
run result:
Python 3.4.1
name ‘let_us_cause_a_NameError’ is not defined —> our error messagenext()
函数 and .next()
方法
因为 next() (.next())
是一个如此普通的使用函数(方法),这里有另外一个语法改变(或者是实现上改变了),值得一提的是:在 Python 2.7.5 中函数和方法你都可以使用,next()
函数在 Python 3 中一直保留着(调用 .next()
抛出属性异常)。
Python 2
1 2 3 4 | print 'Python', python_version() my_generator = (letter for letter in 'abcdefg') next(my_generator) my_generator.next() |
run result:
Python 2.7.6‘b
Python 3
1 2 3 | print( 'Python', python_version()) my_generator = (letter for letter in 'abcdefg') next(my_generator) |
run result:
Python 3.4.1‘a’
1 | my_generator.next() |
run result:
-—————————————————————————————————————AttributeError Traceback (most recent call last)< ipython-input-14-125f388bb61b> in < module>()——> 1 my_generator.next()AttributeError: ‘generator’ object has no attribute ‘next’
For
循环变量和全局命名空间泄漏
好消息:在 Python 3.x 中 for
循环变量不会再导致命名空间泄漏。 在 Python 3.x 中做了一个改变,在 What’s New In Python 3.0 中有如下描述: “列表推导不再支持 [... for var in item1, item2, ...]
这样的语法。使用 [... for var in (item1, item2, ...)]
代替。也需要提醒的是列表推导有不同的语义: 他们关闭了在 list()
构造器中的生成器表达式的语法糖, 并且特别是循环控制变量不再泄漏进周围的作用范围域.”
Python 2
1 2 3 4 5 | print 'Python', python_version() i = 1 print 'before: i =', i print 'comprehension: ', [i for i in range(5)] print 'after: i =', i |
run result:
Python 2.7.6before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 4Python 3
1 2 3 4 5 | print( 'Python', python_version()) i = 1 print( 'before: i =', i) print( 'comprehension:', [i for i in range(5)]) print( 'after: i =', i) |
run result:
Python 3.4.1before: i = 1comprehension: [0, 1, 2, 3, 4]after: i = 1比较不可排序类型
在 Python 3 中的另外一个变化就是当对不可排序类型做比较的时候,会抛出一个类型错误。
Python 2
1 2 3 4 | print 'Python', python_version() print "[1, 2] > 'foo' = ", [1, 2] > 'foo' print "(1, 2) > 'foo' = ", (1, 2) > 'foo' print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2) |
run result:
Python 2.7.6[1, 2] > ‘foo’ = False(1, 2) > ‘foo’ = True[1, 2] > (1, 2) = FalsePython 3
1 2 3 4 | print( 'Python', python_version()) print( "[1, 2] > 'foo' = ", [1, 2] > 'foo') print( "(1, 2) > 'foo' = ", (1, 2) > 'foo') print( "[1, 2] > (1, 2) = ", [1, 2] > (1, 2)) |
run result:
Python 3.4.1-—————————————————————————————————————
TypeError Traceback (most recent call last)< ipython-input-16-a9031729f4a0> in < module>()1 print(‘Python’, python_version())——> 2 print(“[1, 2] > ‘foo’ = “, [1, 2] > ‘foo’)3 print(“(1, 2) > ‘foo’ = “, (1, 2) > ‘foo’)4 print(“[1, 2] > (1, 2) = “, [1, 2] > (1, 2))TypeError: unorderable types: list() > str()
通过input()
解析用户的输入
幸运的是,在 Python 3 中已经解决了把用户的输入存储为一个 str
对象的问题。为了避免在 Python 2 中的读取非字符串类型的危险行为,我们不得不使用 raw_input()
代替。
Python 2
Python 2.7.6[GCC 4.0.1 (Apple Inc. build 5493)] on darwinType “help”, “copyright”, “credits” or “license” for more information.>>> my_input = input('enter a number: ') enter a number: 123 >>> type(my_input)>>> my_input = raw_input('enter a number: ') enter a number: 123 >>> type(my_input)
Python 3
Python 3.4.1[GCC 4.2.1 (Apple Inc. build 5577)] on darwinType “help”, “copyright”, “credits” or “license” for more information.>>> my_input = input('enter a number: ') enter a number: 123 >>> type(my_input)
返回可迭代对象,而不是列表
如果在 xrange 章节看到的,现在在 Python 3 中一些方法和函数返回迭代对象 — 代替 Python 2 中的列表
因为我们通常那些遍历只有一次,我认为这个改变对节约内存很有意义。尽管如此,它也是可能的,相对于生成器 —- 如需要遍历多次。它是不那么高效的。 而对于那些情况下,我们真正需要的是列表对象,我们可以通过list()
函数简单的把迭代对象转换成一个列表。 Python 2
1 2 3 | print 'Python', python_version() print range(3) print type(range(3)) |
run result:
Python 2.7.6[0, 1, 2]< type ‘list’>Python 3
1 2 3 4 | print( 'Python', python_version()) print(range( 3)) print(type(range( 3))) print(list(range( 3))) |
run result:
Python 3.4.1range(0, 3)< class ‘range’>[0, 1, 2] 在 Python 3 中一些经常使用到的不再返回列表的函数和方法:zip()
map()
filter()
- dictionary’s
.keys()
method - dictionary’s
.values()
method - dictionary’s
.items()
method
更多的关于 Python 2 和 Python 3 的文章
下面是我建议后续的关于 Python 2 和 Python 3 的一些好文章。
移植到 Python 3
Python 3 的拥护者和反对者