Heim > Backend-Entwicklung > Python-Tutorial > Wichtige Unterschiede zwischen den Python-Versionen 2.7.x und 3.x

Wichtige Unterschiede zwischen den Python-Versionen 2.7.x und 3.x

不言
Freigeben: 2018-04-24 15:20:46
Original
1747 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich eine Zusammenfassung der wichtigen Unterschiede zwischen den Python-Versionen 2.7.x und 3.x vor. Freunde in Not können darauf zurückgreifen.

Viele Python-Anfänger werden sich fragen: Welche Version von Python soll ich lernen? ? Auf diese Frage lautet meine Antwort normalerweise: „Wählen Sie zunächst ein Python-Tutorial aus, das am besten zu Ihnen passt. Welche Version von Python auch immer im Tutorial verwendet wird, Sie verwenden diese Version. Wenn Sie fast fertig sind, können Sie die Unterschiede zwischen verschiedenen Versionen studieren.“

Aber wenn Sie ein neues Projekt in Python entwickeln möchten, wie wählen Sie dann die Python-Version aus? Ich kann mit gutem Gewissen sagen, dass die meisten Python-Bibliotheken sowohl die Python 2.7.x- als auch die 3.x-Version unterstützen, sodass es egal ist, welche Version Sie wählen, es ist in Ordnung. Um jedoch einige häufige Fallstricke in bestimmten Versionen bei der Verwendung von Python oder bei der Portierung eines Python-Projekts zu vermeiden, ist es dennoch notwendig, die Hauptunterschiede zwischen den beiden gängigen Versionen von Python zu verstehen.

Verzeichnis

  • __future__-Modul verwenden

  • Druckfunktion

  • Ganzzahldivision

  • Unicode

  • xrange

  • Ausnahme auslösen

  • Ausnahme behandeln

  • next()-Funktion und .next()-Methode

  • Für Schleifenvariable und globales Namespace-Leck

  • Ungeordnete Typen vergleichen

  • Verwenden Sie input(), um den Eingabeinhalt zu analysieren

  • Gibt ein iterierbares Objekt anstelle einer Liste zurück

  • Weitere Artikel über Python 2 und Python 3

__future__ module

[Zurück zum Inhalt]

Python 3.x führte einige Schlüsselwörter ein, die mit Python 2 und Funktionen inkompatibel sind, die in Python 2 kann über das integrierte __future__-Modul importiert werden. Wenn Sie möchten, dass in einer Python-2-Umgebung geschriebener Code auch in Python 3.x läuft, empfiehlt sich die Verwendung des Moduls __future__. Wenn Sie beispielsweise das Ganzzahldivisionsverhalten von Python 3.x in Python 2 haben möchten, können Sie das entsprechende Modul mit der folgenden Anweisung importieren.

1

from __future__ import pision

Nach dem Login kopieren

Die folgende Tabelle listet andere importierbare Funktionen in __future__ auf:

特性可选版本强制版本效果
nested_scopes2.1.0b12.2PEP 227:
Statically Nested Scopes
generators2.2.0a12.3PEP 255:
Simple Generators
pision2.2.0a23.0PEP 238:
Changing the pision Operator
absolute_import2.5.0a13.0PEP 328:
Imports: Multi-Line and Absolute/Relative
with_statement2.5.0a12.6PEP 343:
The “with” Statement
print_function2.6.0a23.0PEP 3105:
Make print a function
unicode_literals2.6.0a23.0PEP 3112:
Bytes literals in Python 3000

(来源: https://docs.python.org/2/library/future.html)

示例:

1

from platform import python_version

Nach dem Login kopieren

print函数

[回到目录]

虽然print语法是Python 3中一个很小的改动,且应该已经广为人知,但依然值得提一下:Python 2中的print语句被Python 3中的print()函数取代,这意味着在Python 3中必须用括号将需要输出的对象括起来。

在Python 2中使用额外的括号也是可以的。但反过来在Python 3中想以Python2的形式不带括号调用print函数时,会触发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'

Nach dem Login kopieren

1

2

3

4

Python 2.7.6

Hello, World!

Hello, World!

text print more text on the same line

Nach dem Login kopieren

Python 3

1

2

3

4

5

print('Python', python_version())

print('Hello, World!')

  

print("some text,", end="")

print(' print more text on the same line')

Nach dem Login kopieren

1

2

3

Python 3.4.1

Hello, World!

some text, print more text on the same line

Nach dem Login kopieren

1

print 'Hello, World!'

Nach dem Login kopieren

1

2

3

4

File "<ipython-input-3-139a7c5835bd>", line 1

print &#39;Hello, World!&#39;

^

SyntaxError: invalid syntax</ipython-input-3-139a7c5835bd>

Nach dem Login kopieren

注意:

在Python中,带不带括号输出”Hello World”都很正常。但如果在圆括号中同时输出多个对象时,就会创建一个元组,这是因为在Python 2中,print是一个语句,而不是函数调用。

1

2

3

print &#39;Python&#39;, python_version()

print(&#39;a&#39;, &#39;b&#39;)

print &#39;a&#39;, &#39;b&#39;

Nach dem Login kopieren
Python 2.7.7
(&#39;a&#39;, &#39;b&#39;)
a b
Nach dem Login kopieren

整数除法

[回到目录]

由于人们常常会忽视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 pision来使用Python 3的除法)。

Python 2

1

2

3

4

5

print &#39;Python&#39;, python_version()

print &#39;3 / 2 =&#39;, 3 / 2

print &#39;3 // 2 =&#39;, 3 // 2

print &#39;3 / 2.0 =&#39;, 3 / 2.0

print &#39;3 // 2.0 =&#39;, 3 // 2.0

Nach dem Login kopieren
Python 2.7.6
3 / 2 = 1
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0
Nach dem Login kopieren

Python 3

1

2

3

4

5

print(&#39;Python&#39;, python_version())

print(&#39;3 / 2 =&#39;, 3 / 2)

print(&#39;3 // 2 =&#39;, 3 // 2)

print(&#39;3 / 2.0 =&#39;, 3 / 2.0)

print(&#39;3 // 2.0 =&#39;, 3 // 2.0)

Nach dem Login kopieren
Python 3.4.1
3 / 2 = 1.5
3 // 2 = 1
3 / 2.0 = 1.5
3 // 2.0 = 1.0
Nach dem Login kopieren

Unicode

[回到目录]

Python 2有基于ASCII的str()类型,其可通过单独的unicode()函数转成unicode类型,但没有byte类型。

而在Python 3中,终于有了Unicode(utf-8)字符串,以及两个字节类:bytes和bytearrays。

Python 2

1

print &#39;Python&#39;, python_version()

Nach dem Login kopieren
Nach dem Login kopieren
Python 2.7.6
Nach dem Login kopieren
Nach dem Login kopieren

1

print type(unicode(&#39;this is like a python3 str type&#39;))

Nach dem Login kopieren
<type &#39;unicode&#39;>
Nach dem Login kopieren

1

print type(b&#39;byte type does not exist&#39;)

Nach dem Login kopieren
<type &#39;str&#39;>
Nach dem Login kopieren

1

print &#39;they are really&#39; + b&#39; the same&#39;

Nach dem Login kopieren
they are really the same
Nach dem Login kopieren

1

print type(bytearray(b&#39;bytearray oddly does exist though&#39;))

Nach dem Login kopieren
<type &#39;bytearray&#39;>
Nach dem Login kopieren

Python 3

1

2

print(&#39;Python&#39;, python_version())

print(&#39;strings are now utf-8 u03BCnicou0394é!&#39;)

Nach dem Login kopieren
Python 3.4.1
strings are now utf-8 μnicoΔé!
Nach dem Login kopieren

1

2

print(&#39;Python&#39;, python_version(), end="")

print(&#39; has&#39;, type(b&#39; bytes for storing data&#39;))

Nach dem Login kopieren
Python 3.4.1 has <class &#39;bytes&#39;>
Nach dem Login kopieren

1

2

print(&#39;and Python&#39;, python_version(), end="")

print(&#39; also has&#39;, type(bytearray(b&#39;bytearrays&#39;)))

Nach dem Login kopieren
and Python 3.4.1 also has <class &#39;bytearray&#39;>
Nach dem Login kopieren

1

&#39;note that we cannot add a string&#39; + b&#39;bytes for data&#39;

Nach dem Login kopieren
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
 in ()
----> 1 &#39;note that we cannot add a string&#39; + b&#39;bytes for data&#39;
 
TypeError: Can't convert 'bytes' object to str implicitly
Nach dem Login kopieren

xrange

[回到目录]

在Python 2.x中,经常会用xrange()创建一个可迭代对象,通常出现在“for循环”或“列表/集合/字典推导式”中。

这种行为与生成器非常相似(如”惰性求值“),但这里的xrange-iterable无尽的,意味着可能在这个xrange上无限迭代。

由于xrange的“惰性求知“特性,如果只需迭代一次(如for循环中),range()通常比xrange()快一些。不过不建议在多次迭代中使用range(),因为range()每次都会在内存中重新生成一个列表。

在Python 3中,range()的实现方式与xrange()函数相同,所以就不存在专用的xrange()(在Python 3中使用xrange()会触发NameError)。

1

2

3

4

5

6

7

8

9

10

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

Nach dem Login kopieren

Python 2

1

2

3

4

5

6

7

print &#39;Python&#39;, python_version()

  

print 'ntiming range()'

%timeit test_range(n)

  

print 'nntiming xrange()'

%timeit test_xrange(n)

Nach dem Login kopieren
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
Nach dem Login kopieren

Python 3

1

2

3

4

print(&#39;Python&#39;, python_version())

  

print(&#39;ntiming range()&#39;)

%timeit test_range(n)

Nach dem Login kopieren
Python 3.4.1
 
timing range()
1000 loops, best of 3: 520 µs per loop
Nach dem Login kopieren

1

print(xrange(10))

Nach dem Login kopieren
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
in ()
----> 1 print(xrange(10))
 
NameError: name &#39;xrange&#39; is not defined
Nach dem Login kopieren

Python 3中的range对象中的__contains__方法

另一个值得一提的是,在Python 3.x中,range有了一个新的__contains__方法。__contains__方法可以有效的加快Python 3.x中整数和布尔型的“查找”速度。

1

2

3

4

5

6

7

8

9

10

11

12

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(&#39;Python&#39;, 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)

Nach dem Login kopieren
Python 3.4.1
1 loops, best of 3: 742 ms per loop
1000000 loops, best of 3: 1.19 µs per loop
Nach dem Login kopieren

根据上面的timeit的结果,查找整数比查找浮点数要快大约6万倍。但由于Python 2.x中的range或xrange没有__contains__方法,所以在Python 2中的整数和浮点数的查找速度差别不大。

1

2

3

4

5

6

7

8

9

10

print &#39;Python&#39;, 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)

Nach dem Login kopieren
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
Nach dem Login kopieren

下面的代码证明了Python 2.x中没有__contain__方法:

1

2

print(&#39;Python&#39;, python_version())

range.__contains__

Nach dem Login kopieren
Nach dem Login kopieren
Python 3.4.1
<slot wrapper &#39;__contains__&#39; of &#39;range&#39; objects
Nach dem Login kopieren

1

2

print(&#39;Python&#39;, python_version())

range.__contains__

Nach dem Login kopieren
Nach dem Login kopieren
Python 2.7.7
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
 in ()
1 print &#39;Python&#39;, python_version()
----> 2 range.__contains__
 
AttributeError: 'builtin_function_or_method' object has no attribute '__contains__'
Nach dem Login kopieren

1

2

print(&#39;Python&#39;, python_version())

xrange.__contains__

Nach dem Login kopieren
Python 2.7.7
 
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
in ()
1 print &#39;Python&#39;, python_version()
----> 2 xrange.__contains__
 
AttributeError: type object 'xrange' has no attribute '__contains__'
Nach dem Login kopieren

关于Python 2中xrange()与Python 3中range()之间的速度差异的一点说明:

有读者指出了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

Nach dem Login kopieren

1

2

print(&#39;Python&#39;, python_version())

%timeit test_while()

Nach dem Login kopieren
Python 3.4.1
%timeit test_while()
100 loops, best of 3: 2.68 ms per loop
Nach dem Login kopieren

1

2

print &#39;Python&#39;, python_version()

%timeit test_while()

Nach dem Login kopieren
Python 2.7.6
1000 loops, best of 3: 1.72 ms per loop
Nach dem Login kopieren

触发异常

[回到目录]

Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法(不然会触发SyntaxError):

Python 2

1

print &#39;Python&#39;, python_version()

Nach dem Login kopieren
Nach dem Login kopieren
Python 2.7.6
Nach dem Login kopieren
Nach dem Login kopieren

1

raise IOError, "file error"

Nach dem Login kopieren
Nach dem Login kopieren
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
 in ()
----> 1 raise IOError, "file error"
 
IOError: file error
Nach dem Login kopieren

1

raise IOError("file error")

Nach dem Login kopieren
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
 in ()
----> 1 raise IOError("file error")
 
IOError: file error
Nach dem Login kopieren

Python 3

1

print(&#39;Python&#39;, python_version())

Nach dem Login kopieren
Python 3.4.1
Nach dem Login kopieren

1

raise IOError, "file error"

Nach dem Login kopieren
Nach dem Login kopieren
File "", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax
The proper way to raise an exception in Python 3:
Nach dem Login kopieren

1

2

print(&#39;Python&#39;, python_version())

raise IOError("file error")

Nach dem Login kopieren
Python 3.4.1
 
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
 in ()
1 print(&#39;Python&#39;, python_version())
----> 2 raise IOError("file error")
 
OSError: file error
Nach dem Login kopieren

异常处理

[回到目录]

Python 3中的异常处理也发生了一点变化。在Python 3中必须使用“as”关键字。

Python 2

1

2

3

4

5

print &#39;Python&#39;, python_version()

try:

 let_us_cause_a_NameError

except NameError, err:

 print err, '--> our error message'

Nach dem Login kopieren
Python 2.7.6
name &#39;let_us_cause_a_NameError&#39; is not defined --> our error message
Nach dem Login kopieren

Python 3

1

2

3

4

5

print(&#39;Python&#39;, python_version())

try:

 let_us_cause_a_NameError

except NameError as err:

 print(err, '--> our error message')

Nach dem Login kopieren
Python 3.4.1
name &#39;let_us_cause_a_NameError&#39; is not defined --> our error message
Nach dem Login kopieren

next()函数和.next()方法

[回到目录]

由于会经常用到next()(.next())函数(方法),所以还要提到另一个语法改动(实现方面也做了改动):在Python 2.7.5中,函数形式和方法形式都可以使用,而在Python 3中,只能使用next()函数(试图调用.next()方法会触发AttributeError)。

Python 2

1

2

3

4

print &#39;Python&#39;, python_version()

my_generator = (letter for letter in 'abcdefg')

next(my_generator)

my_generator.next()

Nach dem Login kopieren
Python 2.7.6
&#39;b&#39;
Nach dem Login kopieren

Python 3

1

2

3

print(&#39;Python&#39;, python_version())

my_generator = (letter for letter in 'abcdefg')

next(my_generator)

Nach dem Login kopieren
Python 3.4.1
&#39;a&#39;
Nach dem Login kopieren

1

my_generator.next()

Nach dem Login kopieren
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-14-125f388bb61b> in <module>()
----> 1 my_generator.next()
 
AttributeError: &#39;generator&#39; object has no attribute &#39;next&#39;
Nach dem Login kopieren

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

6

7

8

print &#39;Python&#39;, python_version()

  

i = 1

print 'before: i =', i

  

print 'comprehension: ', [i for i in range(5)]

  

print 'after: i =', i

Nach dem Login kopieren
Python 2.7.6
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 4
Nach dem Login kopieren

Python 3

1

2

3

4

5

6

7

8

print(&#39;Python&#39;, python_version())

  

i = 1

print('before: i =', i)

  

print('comprehension:', [i for i in range(5)])

  

print('after: i =', i)

Nach dem Login kopieren
Python 3.4.1
before: i = 1
comprehension: [0, 1, 2, 3, 4]
after: i = 1
Nach dem Login kopieren

比较无序类型

[回到目录]

Python 3中另一个优秀的改动是,如果我们试图比较无序类型,会触发一个TypeError。

Python 2

1

2

3

4

print &#39;Python&#39;, 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)

Nach dem Login kopieren
Python 2.7.6
[1, 2] > &#39;foo&#39; = False
(1, 2) > &#39;foo&#39; = True
[1, 2] > (1, 2) = False
Nach dem Login kopieren

Python 3

1

2

3

4

print(&#39;Python&#39;, 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))

Nach dem Login kopieren
Python 3.4.1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
 in ()
1 print(&#39;Python&#39;, 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()
Nach dem Login kopieren

通过input()解析用户的输入

[回到目录]

幸运的是,Python 3改进了input()函数,这样该函数就会总是将用户的输入存储为str对象。在Python 2中,为了避免读取非字符串类型会发生的一些危险行为,不得不使用raw_input()代替input()。

Python 2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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 &#39;int'="">

  

>>> my_input = raw_input('enter a number: ')

  

enter a number: 123

  

>>> type(my_input)

<type &#39;str&#39;></type>

Nach dem Login kopieren

Python 3

1

2

3

4

5

6

7

8

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(&#39;enter a number: &#39;)

enter a number: 123

>>> type(my_input)

<class &#39;str&#39;>

Nach dem Login kopieren

返回可迭代对象,而不是列表

[回到目录]

在xrange一节中可以看到,某些函数和方法在Python中返回的是可迭代对象,而不像在Python 2中返回列表。

由于通常对这些对象只遍历一次,所以这种方式会节省很多内存。然而,如果通过生成器来多次迭代这些对象,效率就不高了。

此时我们的确需要列表对象,可以通过list()函数简单的将可迭代对象转成列表。

Python 2

1

2

3

4

print &#39;Python&#39;, python_version()

  

print range(3)

print type(range(3))

Nach dem Login kopieren
Python 2.7.6
[0, 1, 2]
<type &#39;list&#39;>
Nach dem Login kopieren

Python 3

1

2

3

4

print(&#39;Python&#39;, python_version())

print(range(3))

print(type(range(3)))

print(list(range(3)))

Nach dem Login kopieren
Python 3.4.1
range(0, 3)
<class &#39;range&#39;>
[0, 1, 2]
Nach dem Login kopieren

下面列出了Python 3中其他不再返回列表的常用函数和方法:

  • zip()

  • map()

  • filter()

  • 字典的.key()方法

  • 字典的.value()方法

  • 字典的.item()方法

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

[回到目录]

下面列出了其他一些可以进一步了解Python 2和Python 3的优秀文章,

//迁移到 Python 3

  • Should I use Python 2 or Python 3 for my development activity?

  • What's New In Python 3.0

  • Portierung nach Python 3

  • Portierung von Python 2-Code nach Python 3

  • Wie Python 3 vorankommt

// Das Lob und die Kritik an Python 3

  • 10 tolle Funktionen von Python, die Sie nicht nutzen können, weil Sie sich weigern, auf Python 3 zu aktualisieren

  • Python 3 zerstört Python

  • Python 3 kann Python wiederbeleben

  • Python 3 ist in Ordnung

Das obige ist der detaillierte Inhalt vonWichtige Unterschiede zwischen den Python-Versionen 2.7.x und 3.x. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage