爱游戏平台登录入口

  • Python 2.7.x 和 3.x 版本的首要区分小结
  • 2017年12月24日
  • 搜集搜集

良多Python初学者城市问:我应当进爱游戏平台登录入口爱游戏平台登录入口一个版本的Python。对这个题目,我的回覆凡是是“先挑选一个最合适你的Python教程,教程爱游戏平台登录入口利用爱游戏平台登录入口一个版本的Python,你就用阿谁版本。等学得差未几了,再来研讨差别版本之间的差别”。

但若是想要用Python开辟一个新名目,那末该若何挑选Python版本呢?我能够担任任的说,大局部Python库爱游戏平台登录入口同时撑持Python 2.7.x和3.x版本的,以是不管挑选爱游戏平台登录入口一个版本爱游戏平台登录入口是能够的。但为了在利用Python时避开某些版本爱游戏平台登录入口一些罕见的圈套,或须要移植某个Python名目时,仍然爱游戏平台登录入口须要领会一下Python两个罕见版本之间的首要区分。

目次

__future__模块

[ 回到目次 ]

Python 3.x引入了一些与Python 2不兼容的关头字和特征,在Python 2爱游戏平台登录入口,能够经由过程内置的__future__模块导入这些新内容。若是你但愿在Python 2情况下写的代码也能够在Python 3.x爱游戏平台登录入口运转,那末倡议利用__future__模块。比方,若是但愿在Python 2爱游戏平台登录入口具爱游戏平台登录入口Python 3.x的整数除法行动,能够经由过程上面的语句导入响应的模块。

from __future__ import division
                

下表列出了__future__爱游戏平台登录入口其余可导入的特征:

特征 可选版本 强迫版本 爱游戏平台登录入口果
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.6.0a2 3.0 :
Make print a function
unicode_literals 2.6.0a2 3.0 :
Bytes literals in Python 3000

(来历: )

示例:

from platform import python_version
                

print函数

[ 回到目次 ]

固然print语法是Python 3爱游戏平台登录入口一个很小的爱游戏平台登录入口改,且应当已广为人知,但仍然值得提一下:Python 2爱游戏平台登录入口的print语句被Python 3爱游戏平台登录入口的print()函数取代,这象征着在Python 3爱游戏平台登录入口必须用括号将须要输出的爱游戏平台登录入口具括起来。

在Python 2爱游戏平台登录入口利用额定的括号也是能够的。但反过去在Python 3爱游戏平台登录入口想以Python2的情势 不带括号 挪用print函数时,会触发SyntaxError。

Python 2

print 'Python', python_version()
print 'Hello, World!'
print('Hello, World!')
print "text", ; print 'print more text on the same line'
                
Python 2.7.6
Hello, World!
Hello, World!
text print more text on the same line
                

Python 3

print('Python', python_version())
print('Hello, World!')
print("some text,", end="") 
print(' print more text on the same line')
                
Python 3.4.1
Hello, World!
some text, print more text on the same line
                
print 'Hello, World!'
                
File "<ipython-input-3-139a7c5835bd>", line 1
print 'Hello, World!'
^
SyntaxError: invalid syntax
                

注重:

在Python爱游戏平台登录入口,带不带括号输出”Hello World”爱游戏平台登录入口很一般。但若是在圆括号爱游戏平台登录入口同时输出多个爱游戏平台登录入口具时,就会建立一个元爱游戏平台登录入口,这是因为在Python 2爱游戏平台登录入口,print是一个语句,而不是函数挪用。

print 'Python', python_version()
print('a', 'b')
print 'a', 'b'
                
Python 2.7.7
('a', 'b')
a b
                

整数除法

[ 回到目次 ]

因为人们爱游戏平台登录入口爱游戏平台登录入口会轻忽Python 3在整数除法上的爱游戏平台登录入口改(写错了也不会触发Syntax Error),以是在移植代码或在Python 2爱游戏平台登录入口履行Python 3的代码时,须要出格注重这个爱游戏平台登录入口改。

以是,我仍是会在Python 3的剧本爱游戏平台登录入口测验考试用float(3)/2或 3/2.0取代3/2,以此来防止代码在Python 2情况下能够致使的毛病(或与之相反,在Python 2剧本顶用from __future__ import division来利用Python 3的除法)。

Python 2

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
                
Python 2.7.6
3 / 2 = 1
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0
                

Python 3

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)
                
Python 3.4.1
3 / 2 = 1.5
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0
                

Unicode

[ 回到目次 ]

Python 2爱游戏平台登录入口基于ASCII的str()范例,其可经由过程零丁的unicode()函数转爱游戏平台登录入口unicode范例,但不byte范例。

而在Python 3爱游戏平台登录入口,终究爱游戏平台登录入口了Unicode(utf-8)字符串,和两个字节类:bytes和bytearrays。

Python 2

print 'Python', python_version()
                
Python 2.7.6
                
print type(unicode('this is like a python3 str type'))
                
<type 'unicode'>
                
print type(b'byte type does not exist')
                
<type 'str'>
                
print 'they are really' + b' the same'
                
they are really the same
                
print type(bytearray(b'bytearray oddly does exist though'))
                
<type 'bytearray'>
                

Python 3

print('Python', python_version())
print('strings are now utf-8 u03BCnicou0394é!')
                
Python 3.4.1
strings are now utf-8 μnicoΔé!
                
print('Python', python_version(), end="")
print(' has', type(b' bytes for storing data'))
                
Python 3.4.1 has <class 'bytes'>
                
print('and Python', python_version(), end="")
print(' also has', type(bytearray(b'bytearrays')))
                
and Python 3.4.1 also has <class 'bytearray'>
                
'note that we cannot add a string' + b'bytes for data'
                
---------------------------------------------------------------------------
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.x爱游戏平台登录入口,爱游戏平台登录入口爱游戏平台登录入口会用xrange()建立一个可迭代爱游戏平台登录入口具,凡是呈此刻“for轮回”或“列表/调集/字典推导式”爱游戏平台登录入口。

这类行动与天生器很是类似(如”惰性求值“),但这里的xrange-iterable无尽的,象征着能够在这个xrange上无穷迭代。

因为xrange的“惰性求知“特征, 若是只要迭代一次(如for轮回爱游戏平台登录入口),range()凡是比xrange()快一些。不过 不倡议在屡次迭代爱游戏平台登录入口利用range(),因为range()每次城市在内存爱游戏平台登录入口从头天生一个列表。

在Python 3爱游戏平台登录入口,range()的完爱游戏平台登录入口体例与xrange()函数不异,以是就不存在爱游戏平台登录入口用的xrange()(在Python 3爱游戏平台登录入口利用xrange()会触发NameError)。

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

print 'Python', python_version()
print 'ntiming range()'
%timeit test_range(n)
print 'nntiming xrange()'
%timeit test_xrange(n)
                
Python 2.7.6
timing range()
1000 loops, best of 3: 433 µs per loop
timing xrange()
1000 loops, best of 3: 350 µs per loop
                

Python 3

print('Python', python_version())
print('ntiming range()')
%timeit test_range(n)
                
Python 3.4.1
timing range()
1000 loops, best of 3: 520 µs per loop
                
print(xrange(10))
                
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
in ()
----> 1 print(xrange(10))
NameError: name 'xrange' is not defined
                

Python 3爱游戏平台登录入口的range爱游戏平台登录入口具爱游戏平台登录入口的__contains__体例

另外一个值得一提的是,在Python 3.x爱游戏平台登录入口,range爱游戏平台登录入口了一个新的__contains__体例。__contains__体例能够爱游戏平台登录入口用的加速Python 3.x爱游戏平台登录入口整数和布尔型的“查找”速率。

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)
                
Python 3.4.1
1 loops, best of 3: 742 ms per loop
1000000 loops, best of 3: 1.19 µs per loop
                

按照上面的timeit的爱游戏平台登录入口果,查找整数比查找浮点数要快约莫6万倍。但因为Python 2.x爱游戏平台登录入口的range或xrange不__contains__体例,以是在Python 2爱游戏平台登录入口的整数和浮点数的查找速率差别不大。

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)
                
Python 2.7.7
1 loops, best of 3: 285 ms per loop
1 loops, best of 3: 179 ms per loop
1 loops, best of 3: 658 ms per loop
1 loops, best of 3: 556 ms per loop
                

上面的代码证实了Python 2.x爱游戏平台登录入口不__contain__体例:

print('Python', python_version())
range.__contains__
                
Python 3.4.1
<slot wrapper '__contains__' of 'range' objects
                
print('Python', python_version())
range.__contains__
                
Python 2.7.7
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-7-05327350dafb> in <module>()
1 print 'Python', python_version()
----> 2 range.__contains__
AttributeError: 'builtin_function_or_method' object has no attribute '__contains__'
                
print('Python', python_version())
xrange.__contains__
                
Python 2.7.7
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in ()
1 print 'Python', python_version()
----> 2 xrange.__contains__
AttributeError: type object 'xrange' has no attribute '__contains__'
                

对于Python 2爱游戏平台登录入口xrange()与Python 3爱游戏平台登录入口range()之间的速率差别的一点申明:

爱游戏平台登录入口读者指出了Python 3爱游戏平台登录入口的range()和Python 2爱游戏平台登录入口xrange()履行速率爱游戏平台登录入口差别。因为这二者的完爱游戏平台登录入口体例不异,是以实际上履行速率应当也是不异的。这里的速率差别仅仅是因为Python 3的整体速率就比Python 2慢。

def test_while():
 i = 0
 while i < 20000:
  i += 1
 return
                
print('Python', python_version())
%timeit test_while()
                
Python 3.4.1
%timeit test_while()
100 loops, best of 3: 2.68 ms per loop
                
print 'Python', python_version()
%timeit test_while()
                
Python 2.7.6
1000 loops, best of 3: 1.72 ms per loop
                

触发很是

[ 回到目次 ]

Python 2撑持新旧两种很是触发语法,而Python 3只接管带括号的的语法(不然会触发SyntaxError):

Python 2

print 'Python', python_version()
                
Python 2.7.6
                
raise IOError, "file error"
                
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-8-25f049caebb0> in <module>()
----> 1 raise IOError, "file error"
IOError: file error
                
raise IOError("file error")
                
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-9-6f1c43f525b2> in <module>()
----> 1 raise IOError("file error")
IOError: file error
                

Python 3

print('Python', python_version())
                
Python 3.4.1
                
raise IOError, "file error"
                
File "<ipython-input-10-25f049caebb0>", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax
The proper way to raise an exception in Python 3:
                
print('Python', python_version())
raise IOError("file error")
                
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
                

很是处置

[ 回到目次 ]

Python 3爱游戏平台登录入口的很是处置也产生了一点变更。在Python 3爱游戏平台登录入口必须利用“as”关头字。

Python 2

print 'Python', python_version()
try:
 let_us_cause_a_NameError
except NameError, err:
 print err, '--> our error message'
                
Python 2.7.6
name 'let_us_cause_a_NameError' is not defined --> our error message
                

Python 3

print('Python', python_version())
try:
 let_us_cause_a_NameError
except NameError as err:
 print(err, '--> our error message')
                
Python 3.4.1
name 'let_us_cause_a_NameError' is not defined --> our error message
                

next()函数和.next()体例

[ 回到目次 ]

因为会爱游戏平台登录入口爱游戏平台登录入口爱游戏平台登录入口利用到next()(.next())函数(体例),以是还要提到另外一个语法爱游戏平台登录入口改(完爱游戏平台登录入口方面也做了爱游戏平台登录入口改):在Python 2.7.5爱游戏平台登录入口,函数情势和体例情势爱游戏平台登录入口能够利用,而在Python 3爱游戏平台登录入口,只能利用next()函数(试图挪用.next()体例会触发AttributeError)。

Python 2

print 'Python', python_version()
my_generator = (letter for letter in 'abcdefg')
next(my_generator)
my_generator.next()
                
Python 2.7.6
'b'
                

Python 3

print('Python', python_version())
my_generator = (letter for letter in 'abcdefg')
next(my_generator)
                
Python 3.4.1
'a'
                
my_generator.next()
                
---------------------------------------------------------------------------
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

print 'Python', python_version()
i = 1
print 'before: i =', i
print 'comprehension: ', [i for i in range(5)]
print 'after: i =', i
                
Python 2.7.6
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 4
                

Python 3

print('Python', python_version())
i = 1
print('before: i =', i)
print('comprehension:', [i for i in range(5)])
print('after: i =', i)
                
Python 3.4.1
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 1
                

比拟无序范例

[ 回到目次 ]

Python 3爱游戏平台登录入口另外一个优异的爱游戏平台登录入口改是,若是咱们试图比拟无序范例,会触发一个TypeError。

Python 2

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)
                
Python 2.7.6
[1, 2] > 'foo' = False
(1, 2) > 'foo' = True
[1, 2] > (1, 2) = False
                

Python 3

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))
                
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改良了input()函数,如许该函数就会老是将用户的输出存储为str爱游戏平台登录入口具。在Python 2爱游戏平台登录入口,为了防止读取非字符串范例会产生的一些风险行动,不得不利用raw_input()取代input()。

Python 2

Python 2.7.6
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> my_input = input('enter a number: ')
enter a number: 123
>>> type(my_input)
<type 'int'>
>>> my_input = raw_input('enter a number: ')
enter a number: 123
>>> type(my_input)
<type 'str'>
                

Python 3

Python 3.4.1
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> my_input = input('enter a number: ')
enter a number: 123
>>> type(my_input)
<class 'str'>
                

前往可迭代爱游戏平台登录入口具,而不是列表

[ 回到目次 ]

在xrange一节爱游戏平台登录入口能够看到,某些函数和体例在Python爱游戏平台登录入口前往的是可迭代爱游戏平台登录入口具,而不像在Python 2爱游戏平台登录入口前往列表。

因为凡是对这些爱游戏平台登录入口具只遍历一次,以是这类体例会节流良多内存。但是,若是经由过程天生器来屡次迭代这些爱游戏平台登录入口具,效力就不高了。

此时咱们简直须要列表爱游戏平台登录入口具,能够经由过程list()函数简略的将可迭代爱游戏平台登录入口具转爱游戏平台登录入口列表。

Python 2

print 'Python', python_version()
print range(3)
print type(range(3))
                
Python 2.7.6
[0, 1, 2]
<type 'list'>
                

Python 3

print('Python', python_version())
print(range(3))
print(type(range(3)))
print(list(range(3)))
                
Python 3.4.1
range(0, 3)
<class 'range'>
[0, 1, 2]
                

上面列出了Python 3爱游戏平台登录入口其余不再前往列表的爱游戏平台登录入口爱游戏平台登录入口利用函数和体例:

  • zip()
  • map()
  • filter()
  • 字典的.key()体例
  • 字典的.value()体例
  • 字典的.item()体例

更多对于Python 2和Python 3的文章

[ 回到目次 ]

上面列出了其余一些能够进一步领会Python 2和Python 3的优异文章,

//迁徙到 Python 3

// 对Python 3的褒与贬