Suche…


Einführung

Im Gegensatz zu den meisten Sprachen unterstützt Python zwei Hauptversionen. Seit 2008, als Python 3 veröffentlicht wurde, haben viele den Übergang vollzogen, viele jedoch nicht. In beiden Abschnitten werden die wichtigsten Unterschiede zwischen Python 2 und Python 3 erläutert.

Bemerkungen

Momentan gibt es zwei unterstützte Versionen von Python: 2.7 (Python 2) und 3.6 (Python 3). Zusätzlich erhalten die Versionen 3.3 und 3.4 Sicherheitsupdates im Quellformat.

Python 2.7 ist abwärtskompatibel mit den meisten früheren Python-Versionen und kann Python-Code in den meisten 1.x- und 2.x-Versionen von Python unverändert ausführen. Es ist breit verfügbar, mit einer umfangreichen Sammlung von Paketen. Es wird auch von den CPython-Entwicklern als veraltet eingestuft und erhält nur Sicherheits- und Bugfix-Entwicklungen. Die CPython-Entwickler beabsichtigen, diese Version der Sprache im Jahr 2020 aufzugeben.

Laut Python Enhancement Proposal 373 sind nach dem 25. Juni 2016 keine zukünftigen zukünftigen Versionen von Python 2 geplant, aber Bug-Fixes und Sicherheitsupdates werden bis 2020 unterstützt. (Es wird nicht angegeben, welches Datum in 2020 das Verfallsdatum von Python sein wird 2.)

Python 3 brach absichtlich die Rückwärtskompatibilität auf, um die Bedenken der Sprachentwickler mit dem Kern der Sprache zu berücksichtigen. Python 3 erhält neue Entwicklungen und neue Funktionen. Es ist die Version der Sprache, mit der die Sprachentwickler fortfahren möchten.

In der Zeit zwischen der ersten Version von Python 3.0 und der aktuellen Version wurden einige Funktionen von Python 3 in Python 2.6 zurückportiert, und andere Teile von Python 3 wurden erweitert, um eine mit Python 2 kompatible Syntax zu erhalten. Daher ist das Schreiben möglich Python, das sowohl für Python 2 als auch für Python 3 verwendet werden kann, indem zukünftige Importe und spezielle Module (wie sechs ) verwendet werden.

Zukünftige Importe müssen am Anfang Ihres Moduls stehen:

from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')

Weitere Informationen zum __future__ Modul finden Sie auf der entsprechenden Seite in der Python-Dokumentation .

Das 2to3-Tool ist ein Python-Programm, das Python 2.x-Code in Python 3.x-Code konvertiert, siehe auch die Python-Dokumentation .

Das Paket 6 enthält Dienstprogramme für die Python 2/3-Kompatibilität:

  • einheitlicher Zugriff auf umbenannte Bibliotheken
  • Variablen für String- / Unicode-Typen
  • Funktionen für Methoden, die entfernt oder umbenannt wurden

Eine Referenz für Unterschiede zwischen Python 2 und Python 3 finden Sie hier .

Anweisung drucken vs. Druckfunktion

In Python 2 ist print eine Aussage:

Python 2.x 2.7
print "Hello World"
print                         # print a newline
print "No newline",           # add trailing comma to remove newline 
print >>sys.stderr, "Error"   # print to stderr
print("hello")                # print "hello", since ("hello") == "hello"
print()                       # print an empty tuple "()"
print 1, 2, 3                 # print space-separated arguments: "1 2 3"
print(1, 2, 3)                # print tuple "(1, 2, 3)"

In Python 3 ist print() eine Funktion mit Schlüsselwortargumenten für allgemeine Zwecke:

Python 3.x 3.0
print "Hello World"              # SyntaxError
print("Hello World")
print()                          # print a newline (must use parentheses)
print("No newline", end="")      # end specifies what to append (defaults to newline)
print("Error", file=sys.stderr)  # file specifies the output buffer
print("Comma", "separated", "output", sep=",")  # sep specifies the separator
print("A", "B", "C", sep="")     # null string for sep: prints as ABC
print("Flush this", flush=True)  # flush the output buffer, added in Python 3.3
print(1, 2, 3)                   # print space-separated arguments: "1 2 3"
print((1, 2, 3))                 # print tuple "(1, 2, 3)"

Die Druckfunktion hat folgende Parameter:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

sep trennt die Objekte, die Sie zum Drucken übergeben. Zum Beispiel:

print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar

end ist das Ende der Druckanweisung, gefolgt von. Zum Beispiel:

print('foo', 'bar', end='!') # out: foo bar!

Ein erneuter Druckvorgang nach einer Anweisung, die nicht am Zeilenende endet, wird in derselben Zeile gedruckt:

print('foo', end='~')
print('bar')
# out: foo~bar

Hinweis: Für zukünftige Kompatibilität, print auch in Python 2.6 ab zur Verfügung steht; Sie kann jedoch nur verwendet werden, wenn das Analysieren der Anweisung print mit deaktiviert ist

from __future__ import print_function

Diese Funktion hat genau dasselbe Format wie Python 3, jedoch fehlt der flush Parameter.

Weitere Informationen finden Sie in PEP 3105 .

Zeichenfolgen: Bytes im Vergleich zu Unicode

Python 2.x 2.7

In Python 2 gibt es zwei Varianten von string: Bytes mit Typ ( str ) und solche mit Text (Type) ( unicode ).

In Python 2 ist ein Objekt vom Typ str immer eine Bytefolge, wird jedoch häufig für Text- und Binärdaten verwendet.

Ein String-Literal wird als Byte-String interpretiert.

s = 'Cafe'    # type(s) == str

Es gibt zwei Ausnahmen: Sie können ein Unicode- (Text-) Literal explizit definieren, indem Sie dem Literal das Präfix u voranstellen:

s = u'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == str

Alternativ können Sie angeben, dass die String-Literale eines ganzen Moduls Unicode-Textliterale erstellen sollen:

from __future__ import unicode_literals

s = 'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == unicode

Um zu prüfen, ob Ihre Variable eine Zeichenfolge ist (entweder Unicode oder eine Byte-Zeichenfolge), können Sie Folgendes verwenden:

isinstance(s, basestring)
Python 3.x 3.0

In Python 3 ist der str Typ ein Unicode-Texttyp.

s = 'Cafe'           # type(s) == str
s = 'Café'           # type(s) == str (note the accented trailing e)

Darüber hinaus fügte Python 3 ein bytes Objekt hinzu , das für binäre "Blobs" oder zum Schreiben in codierungsunabhängige Dateien geeignet ist. Um ein Byte-Objekt zu erstellen, können Sie ein String-Literal mit einem Präfix b oder die encode Methode des Strings aufrufen:

# Or, if you really need a byte string:
s = b'Cafe'          # type(s) == bytes
s = 'Café'.encode()  # type(s) == bytes

Um zu testen, ob ein Wert eine Zeichenfolge ist, verwenden Sie:

isinstance(s, str)
Python 3.x 3.3

Es ist auch möglich, String-Literalen ein Präfix " u voranzustellen, um die Kompatibilität zwischen Python 2- und Python 3-Codebasen zu erleichtern. Da in Python 3 standardmäßig alle Zeichenfolgen Unicode sind, hat das Voranstellen eines Zeichenfolgenlitals mit u keine Auswirkungen:

u'Cafe' == 'Cafe'

Das unformatierte Unicode-String-Präfix ur Python 2 wird jedoch nicht unterstützt:

>>> ur'Café'
  File "<stdin>", line 1
    ur'Café'
           ^
SyntaxError: invalid syntax

Beachten Sie, dass Sie ein Python 3-Textobjekt ( str ) encode müssen, um es in eine bytes Darstellung dieses Texts zu konvertieren. Die Standardkodierung dieser Methode ist UTF-8 .

Sie können decode , um ein bytes nach dem Unicode-Text zu fragen:

>>> b.decode()
'Café'
Python 2.x 2.6

Während der bytes Typ sowohl in Python 2 als auch in 3 vorhanden ist, ist der unicode Typ nur in Python 2 vorhanden. Um implizite Unicode-Zeichenfolgen von Python 3 in Python 2 zu verwenden, fügen Sie Folgendes in Ihre Codedatei ein:

from __future__ import unicode_literals
print(repr("hi"))
# u'hi'
Python 3.x 3.0

Ein weiterer wichtiger Unterschied ist, dass die Indizierung von Bytes in Python 3 zu einer int Ausgabe führt:

b"abc"[0] == 97

Wenn Sie in einer Größe von 1 schneiden, erhalten Sie ein Objekt mit der Länge 1 Byte:

b"abc"[0:1] == b"a"

Darüber hinaus behebt Python 3 einige ungewöhnliche Verhaltensweisen beim Unicode, dh das Umkehren von Bytezeichenfolgen in Python 2. Zum Beispiel wurde das folgende Problem behoben:

# -*- coding: utf8 -*-
print("Hi, my name is Łukasz Langa.")
print(u"Hi, my name is Łukasz Langa."[::-1])
print("Hi, my name is Łukasz Langa."[::-1])

# Output in Python 2
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsaku�� si eman ym ,iH

# Output in Python 3
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsakuŁ si eman ym ,iH

Integer Division

Das Standard- Divisionssymbol ( / ) funktioniert in Python 3 und Python 2 unterschiedlich, wenn es auf Ganzzahlen angewendet wird.

Beim Dividieren einer Ganzzahl durch eine andere Ganzzahl in Python 3 stellt die Divisionsoperation x / y eine echte Division dar (verwendet __truediv__ Methode __truediv__ ) und erzeugt ein Fließkomma-Ergebnis. Die gleiche Operation in Python 2 stellt eine klassische Division dar , die das Ergebnis in Richtung negative Unendlichkeit abrundet (auch bekannt als das Wort ergreifen ).

Zum Beispiel:

Code Python 2-Ausgabe Python 3-Ausgabe
3 / 2 1 1,5
2 / 3 0 0,6666666666666666
-3 / 2 -2 -1,5

Das Rundungsverhalten gegen Null wurde in Python 2.2 nicht mehr unterstützt , bleibt aber aus Gründen der Abwärtskompatibilität in Python 2.7 und wurde in Python 3 entfernt.

Hinweis: Um ein Fließergebnis in Python 2 (ohne Rundung) zu erhalten, können wir einen der Operanden mit dem Dezimalpunkt angeben. Das obige Beispiel von 2/3 das in Python 2 0 ergibt, wird als 2 / 3.0 oder 2.0 / 3 oder 2.0/3.0 , um 0.6666666666666666 zu erhalten

Code Python 2-Ausgabe Python 3-Ausgabe
3.0 / 2.0 1,5 1,5
2 / 3.0 0,6666666666666666 0,6666666666666666
-3.0 / 2 -1,5 -1,5

Es gibt auch den Floor-Division-Operator ( // ), der in beiden Versionen gleich funktioniert: Er wird auf die nächste Ganzzahl abgerundet. (obwohl bei Verwendung von Floats ein Float zurückgegeben wird) In beiden Versionen ist der // Operator __floordiv__ .

Code Python 2-Ausgabe Python 3-Ausgabe
3 // 2 1 1
2 // 3 0 0
-3 // 2 -2 -2
3.0 // 2.0 1,0 1,0
2.0 // 3 0,0 0,0
-3 // 2.0 -2,0 -2,0

Man kann eine echte Division oder eine Bodendivision explizit durch native Funktionen im operator erzwingen:

from operator import truediv, floordiv
assert truediv(10, 8) == 1.25            # equivalent to `/` in Python 3
assert floordiv(10, 8) == 1              # equivalent to `//`

Die Verwendung von Bedienfunktionen für jeden Bereich kann zwar klar und explizit sein, jedoch langwierig sein. Das Verhalten des Operators / ändern wird häufig bevorzugt. Es ist üblich, das typische Abteilungsverhalten zu eliminieren, indem from __future__ import division die erste Anweisung in jedem Modul hinzugefügt wird:

# needs to be the first statement in a module
from __future__ import division
Code Python 2-Ausgabe Python 3-Ausgabe
3 / 2 1,5 1,5
2 / 3 0,6666666666666666 0,6666666666666666
-3 / 2 -1,5 -1,5

from __future__ import division garantiert, dass der Operator / eine echte Division darstellt, und zwar nur innerhalb der Module, die den __future__ Import enthalten. __future__ gibt es keine zwingenden Gründe, die nicht in allen neuen Modulen aktiviert werden.

Hinweis : Einige andere Programmiersprachen verwenden eine Rundung gegen Null (Verkürzung) und nicht wie Python eine negative Unendlichkeit (dh in diesen Sprachen -3 / 2 == -1 ). Dieses Verhalten kann zu Verwirrung beim Portieren oder Vergleichen von Code führen.


Hinweis zu Float-Operanden : Als Alternative zur from __future__ import division kann man das übliche Divisionssymbol / und sicherstellen, dass mindestens einer der Operanden ein Float ist: 3 / 2.0 == 1.5 . Dies kann jedoch als schlechte Praxis betrachtet werden. Es ist einfach zu einfach, average = sum(items) / len(items) zu schreiben und vergessen, eines der Argumente in Float zu setzen. Darüber hinaus kann es vorkommen, dass solche Fälle während des Testens häufig nicht beachtet werden, z. B. wenn Sie ein Array mit float Werten testen, aber ein Array mit int Werten in der Produktion erhalten. Wenn derselbe Code in Python 3 verwendet wird, funktionieren Programme, die erwarten, dass 3/2 3 / 2 == 1 True ist, nicht ordnungsgemäß.

In PEP 238 finden Sie detailliertere Gründe, warum der Abteilungsoperator in Python 3 geändert wurde und warum eine Aufteilung nach alter Art vermieden werden sollte.


Weitere Informationen zur Unterteilung finden Sie im Thema Simple Math .

Reduzieren ist kein integrierter Bestandteil mehr

In Python 2, reduce ist entweder als eine integrierte Funktion oder von dem functools - Paket (Version 2.6 ab), während in Python 3 reduce nur verfügbar ist functools . Die Syntax für das reduce in Python2 und Python3 ist jedoch dieselbe und wird reduce(function_to_reduce, list_to_reduce) .

Nehmen wir als Beispiel an, eine Liste auf einen einzelnen Wert zu reduzieren, indem Sie jede der benachbarten Zahlen teilen. Hier verwenden wir die truediv Funktion aus der operator Bibliothek.

In Python 2.x ist es so einfach wie:

Python 2.x 2.3
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator
>>> reduce(operator.truediv, my_list)
0.008333333333333333

In Python 3.x wird das Beispiel etwas komplizierter:

Python 3.x 3.0
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator, functools
>>> functools.reduce(operator.truediv, my_list)
0.008333333333333333

Wir können auch from functools import reduce , um das Aufrufen von reduce mit dem Namensraumnamen zu vermeiden.

Unterschiede zwischen Range- und Xrange-Funktionen

In Python 2 gibt die range Funktion eine Liste zurück, während xrange ein spezielles xrange Objekt erstellt. xrange handelt es sich um eine unveränderliche Sequenz, die im Gegensatz zu anderen integrierten Sequenztypen keine Slicing-Funktion unterstützt und keine index oder count Methoden hat:

Python 2.x 2.3
print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

In Python 3 wurde xrange um die range erweitert, wodurch nun ein range wird. Es gibt keinen xrange Typ:

Python 3.x 3.0
print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

Darüber hinaus unterstützt range seit Python 3.2 auch das Schneiden, index und count :

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

Die Verwendung eines speziellen Sequenztyps anstelle einer Liste hat den Vorteil, dass der Interpreter keinen Speicher für eine Liste reservieren und diese füllen muss:

Python 2.x 2.3
# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

Da das letztere Verhalten im Allgemeinen erwünscht ist, wurde das erstere in Python 3 entfernt. Wenn Sie noch eine Liste in Python 3 haben möchten, können Sie den Konstruktor list() einfach für ein range :

Python 3.x 3.0
print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Kompatibilität

Um die Kompatibilität zwischen beiden Versionen von Python 2.x und Python 3.x aufrechtzuerhalten, können Sie das builtins Modul aus dem externen Paket future , um sowohl Vorwärtskompatibilität als auch Rückwärtskompatibilität zu erreichen:

Python 2.x 2.0
#forward-compatible
from builtins import range

for i in range(10**8):
    pass
Python 3.x 3.0
#backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

Der range in der future Bibliothek unterstützt das Aufteilen, index und count in allen Python-Versionen, genau wie die in Python 3.2+ integrierte Methode.

Iterables auspacken

Python 3.x 3.0

In Python 3 können Sie ein iterierbares Paket auspacken, ohne die genaue Anzahl der darin enthaltenen Elemente zu kennen, und sogar eine Variable muss das Ende des iterierbaren Elements enthalten. Dafür geben Sie eine Variable an, die eine Liste von Werten erfassen kann. Dazu wird vor dem Namen ein Sternchen eingefügt. Zum Beispiel das Auspacken einer list :

first, second, *tail, last = [1, 2, 3, 4, 5]
print(first)
# Out: 1
print(second)
# Out: 2
print(tail)
# Out: [3, 4]
print(last)
# Out: 5

Hinweis : Wenn Sie die *variable , ist die variable immer eine Liste, auch wenn der Originaltyp keine Liste war. Abhängig von der Anzahl der Elemente in der ursprünglichen Liste kann es null oder mehr Elemente enthalten.

first, second, *tail, last = [1, 2, 3, 4]
print(tail)
# Out: [3]

first, second, *tail, last = [1, 2, 3]
print(tail)
# Out: []
print(last)
# Out: 3

Entpacken eines str :

begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']

Beispiel für das Auspacken eines date ; _ wird in diesem Beispiel als Wegwerfvariable verwendet (wir interessieren uns nur für den year ):

person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016

Es ist erwähnenswert, dass Sie, da * eine variable Anzahl von Elementen auffrisst, nicht zwei * s für dieselbe Iteration in einer Zuweisung haben können :

*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment
Python 3.x 3.5

Bisher haben wir das Auspacken in Aufgaben besprochen. * und ** wurden in Python 3.5 erweitert . Es ist jetzt möglich, mehrere Auspackvorgänge in einem Ausdruck auszuführen:

{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}
Python 2.x 2.0

Es ist auch möglich, ein iterierbares in Funktionsargumente zu entpacken:

iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5
Python 3.x 3.5

Beim Auspacken eines Wörterbuchs werden zwei benachbarte Sterne ** ( PEP 448 ) verwendet:

tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
 # Out: {'x': 1, 'y': 2, 'z': 3}

Dies ermöglicht das Überschreiben alter Werte und das Zusammenführen von Wörterbüchern.

dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}
Python 3.x 3.0

Python 3 entfernte das Tupel beim Auspacken von Funktionen. Daher funktioniert das Folgende in Python 3 nicht

# Works in Python 2, but syntax error in Python 3:
map(lambda (x, y): x + y, zip(range(5), range(5)))
# Same is true for non-lambdas:
def example((x, y)):
    pass

# Works in both Python 2 and Python 3:
map(lambda x: x[0] + x[1], zip(range(5), range(5)))
# And non-lambdas, too:
def working_example(x_y):
    x, y = x_y
    pass

Ausführliche Informationen finden Sie in PEP 3113 .

Ausnahmen erhöhen und behandeln

Dies ist die Python 2 Syntax, die Kommas beachten , auf die raise und except Linien:

Python 2.x 2.3
try:
    raise IOError, "input/output error"
except IOError, exc:
    print exc

In Python 3, die , wird Syntax fallen gelassen und ersetzt durch die Klammer und die as Stichwort:

try:
    raise IOError("input/output error")
except IOError as exc:
    print(exc)

Aus Gründen der Rückwärtskompatibilität ist die Python 3-Syntax auch in Python 2.6 verfügbar. Sie sollte daher für alle neuen Codes verwendet werden, die nicht mit früheren Versionen kompatibel sind.


Python 3.x 3.0

Python 3 fügt außerdem eine Ausnahme-Verkettung hinzu , wobei Sie signalisieren können, dass eine andere Ausnahme die Ursache für diese Ausnahme war. Zum Beispiel

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from e

Die Ausnahme, die in der except Anweisung __cause__ wird, ist vom Typ DatabaseError , aber die ursprüngliche Ausnahme wird als das Attribut __cause__ dieser Ausnahme markiert. Wenn das Traceback angezeigt wird, wird die ursprüngliche Ausnahme auch im Traceback angezeigt:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Wenn Sie in einem Wurf except Block ohne explizite Verkettungs:

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}')

Das Traceback ist

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Python 2.x 2.0

Keiner wird in Python 2.x unterstützt. Die ursprüngliche Ausnahme und ihr Traceback gehen verloren, wenn im Ausnahmeblock eine andere Ausnahme ausgelöst wird. Der folgende Code kann zur Kompatibilität verwendet werden:

import sys
import traceback

try:
    funcWithError()
except:
    sys_vers = getattr(sys, 'version_info', (0,))
    if sys_vers < (3, 0):
        traceback.print_exc()
    raise Exception("new exception")
Python 3.x 3.3

Um die zuvor geworfene Ausnahme zu "vergessen", verwenden Sie die raise from None

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from None

Nun wäre das Traceback einfach

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Oder um es mit Python 2 und 3 kompatibel zu machen, können Sie das Paket sechs wie folgt verwenden:

import six
try:
    file = open('database.db')
except FileNotFoundError as e:
    six.raise_from(DatabaseError('Cannot open {}'), None)

.next () -Methode für Iteratoren umbenannt

In Python 2 kann ein Iterator durchlaufen werden, indem eine Methode aufgerufen wird, die als next auf dem Iterator selbst aufgerufen wird:

Python 2.x 2.3
g = (i for i in range(0, 3))
g.next()  # Yields 0
g.next()  # Yields 1
g.next()  # Yields 2

In Python 3 wurde die .next Methode in .__next__ umbenannt, .__next__ ihre "magische" Rolle bestätigt, sodass der Aufruf von .next einen AttributeError .next . Der korrekte Weg, um auf diese Funktionalität in Python 2 und Python 3 zuzugreifen, besteht darin, die next Funktion mit dem Iterator als Argument aufzurufen.

Python 3.x 3.0
g = (i for i in range(0, 3))
next(g)  # Yields 0
next(g)  # Yields 1
next(g)  # Yields 2

Dieser Code ist von Version 2.6 bis zu aktuellen Versionen portierbar.

Vergleich verschiedener Typen

Python 2.x 2.3

Objekte verschiedener Typen können verglichen werden. Die Ergebnisse sind willkürlich, aber konsistent. Sie sind so angeordnet, dass None weniger als alles andere ist, numerische Typen sind kleiner als nicht numerische Typen und alles andere ist lexikographisch nach Typ geordnet. Ein int ist also kleiner als ein str und ein tuple ist größer als eine list :

[1, 2] > 'foo'
# Out: False
(1, 2) > 'foo'
# Out: True
[1, 2] > (1, 2)
# Out: False
100 < [1, 'x'] < 'xyz' < (1, 'x')
# Out: True

Dies wurde ursprünglich durchgeführt, damit eine Liste gemischter Typen sortiert werden konnte und Objekte nach Typ gruppiert wurden:

l = [7, 'x', (1, 2), [5, 6], 5, 8.0, 'y', 1.2, [7, 8], 'z']
sorted(l)
# Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'x', 'y', 'z', (1, 2)]
Python 3.x 3.0

Beim Vergleich verschiedener (nicht numerischer) Typen wird eine Ausnahme ausgelöst:

1 < 1.5
# Out: True

[1, 2] > 'foo'
# TypeError: unorderable types: list() > str()
(1, 2) > 'foo'
# TypeError: unorderable types: tuple() > str()
[1, 2] > (1, 2)
# TypeError: unorderable types: list() > tuple()

Um gemischte Listen in Python 3 nach Typen zu sortieren und Kompatibilität zwischen Versionen zu erreichen, müssen Sie einen Schlüssel für die sortierte Funktion angeben:

>>> list = [1, 'hello', [3, 4], {'python': 2}, 'stackoverflow', 8, {'python': 3}, [5, 6]]
>>> sorted(list, key=str)
# Out: [1, 8, [3, 4], [5, 6], 'hello', 'stackoverflow', {'python': 2}, {'python': 3}]

Wenn Sie str als key verwenden, wird jedes Element nur zu Vergleichszwecken temporär in eine Zeichenfolge umgewandelt. Anschließend wird die Zeichenfolgendarstellung mit [ , ' , { oder 0-9 beginnend 0-9 Sie kann diese (und alle folgenden Zeichen) sortieren.

Benutzereingabe

In Python 2 werden Benutzereingaben mit der Funktion raw_input akzeptiert.

Python 2.x 2.3
user_input = raw_input()

Während in Python 3 eine Benutzereingabe unter Verwendung der akzeptierten input

Python 3.x 3.0
user_input = input()

In Python 2 ist der input wird Funktionseingabe akzeptieren und interpretieren. Dies ist zwar nützlich, hat jedoch mehrere Sicherheitsaspekte und wurde in Python 3 entfernt. Für den Zugriff auf dieselbe Funktionalität kann eval(input()) verwendet werden.

Um ein Skript für die beiden Versionen portabel zu halten, können Sie den folgenden Code oben in Ihr Python-Skript einfügen:

try:
    input = raw_input
except NameError:
    pass

Wörterbuchmethode ändert sich

In Python 3 unterscheiden sich viele der Wörterbuchmethoden ziemlich von Python 2, und viele wurden ebenfalls entfernt: has_key , iter* und view* sind weg. Anstelle von d.has_key(key) , der lange veraltet war, muss man jetzt key in d .

In Python 2 geben die keys , values und items Wörterbuchmethoden Listen zurück. In Python 3 geben sie stattdessen Ansichtsobjekte zurück . Die Ansichtsobjekte sind keine Iteratoren und unterscheiden sich in zweierlei Hinsicht von ihnen:

  • Sie haben Größe (man kann die len Funktion verwenden)
  • Sie können viele Male wiederholt werden

Wie bei Iteratoren spiegeln sich auch die Änderungen im Wörterbuch in den Ansichtsobjekten wider.

Python 2.7 hat diese Methoden aus Python 3 zurückportiert; Sie sind als viewkeys , viewvalues und viewitems . Um Python 2-Code in Python 3-Code umzuwandeln, lauten die entsprechenden Formulare:

  • d.keys() , d.values() und d.items() von Python 2 sollten in list(d.keys()) , list(d.values()) und list(d.items())
  • d.iterkeys() , d.itervalues() und d.iteritems() sollten in iter(d.keys()) oder noch besser iter(d) geändert werden. iter(d.values()) bzw. iter(d.items())
  • und schließlich kann die Methode Python 2.7 d.viewkeys() , d.viewvalues() und d.viewitems() durch d.keys() , d.values() und d.items() .

Das Portieren von Python 2-Code, der während der Mutation über Wörterbuchschlüssel, -werte oder -elemente iteriert , ist manchmal schwierig. Erwägen:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
    if key.isalpha():
        del d[key]

Der Code sieht so aus, als würde er in Python 3 ähnlich funktionieren, aber die keys Methode gibt ein Ansichtsobjekt zurück, keine Liste. Wenn das Wörterbuch die Größe ändert, während es iteriert wird, stürzt der Python 3-Code mit der RuntimeError: dictionary changed size during iteration . Die Lösung ist natürlich, for key in list(d) richtig zu schreiben.

In ähnlicher Weise verhalten sich Ansichtsobjekte anders als Iteratoren: Sie können next() für sie verwenden, und Sie können die Iteration nicht fortsetzen . es würde stattdessen neu starten; wenn Python 2 - Code den Rückgabewert gibt d.iterkeys() , d.itervalues() oder d.iteritems() ein Verfahren , das ein Iterator anstelle eines iterable erwartet, dass dann sollte iter(d) , iter(d.values()) oder iter(d.items()) in Python 3.

exec-Anweisung ist eine Funktion in Python 3

In Python 2 ist exec eine Anweisung mit einer speziellen Syntax: exec code [in globals[, locals]]. In Python 3 ist exec nun eine Funktion: exec(code, [, globals[, locals]]) und die Python 2-Syntax SyntaxError einen SyntaxError .

Da print von der Anweisung in eine Funktion __future__ wurde, wurde auch ein __future__ Import hinzugefügt. Es gibt jedoch keine from __future__ import exec_function , da dies nicht erforderlich ist: Die exec-Anweisung in Python 2 kann auch mit einer Syntax verwendet werden, die genau dem Aufruf der exec Funktion in Python 3 entspricht. Sie können also die Anweisungen ändern

Python 2.x 2.3
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars

zu formen

Python 3.x 3.0
exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)

und die letzteren Formen funktionieren garantiert in Python 2 und Python 3 identisch.

hasattr-Funktionsfehler in Python 2

Wenn in Python 2 eine Eigenschaft einen Fehler hasattr , ignoriert hasattr diese Eigenschaft und gibt False .

class A(object):
    @property
    def get(self):
        raise IOError


class B(object):
    @property
    def get(self):
        return 'get in b'

a = A()
b = B()

print 'a hasattr get: ', hasattr(a, 'get')
# output False in Python 2 (fixed, True in Python 3)
print 'b hasattr get', hasattr(b, 'get')
# output True in Python 2 and Python 3

Dieser Fehler wurde in Python3 behoben. Wenn Sie also Python 2 verwenden, verwenden Sie

try:
    a.get
except AttributeError:
    print("no get property!")

oder getattr stattdessen getattr

p = getattr(a, "get", None)
if p is not None:
    print(p)
else:
    print("no get property!")

Umbenannte Module

Einige Module der Standardbibliothek wurden umbenannt:

Alte Bezeichnung Neuer Name
_winreg Winreg
ConfigParser configparser
copy_reg copyreg
Warteschlange Warteschlange
SocketServer Socketserver
_markupbase Markupbase
Repr verdanken
test.test_support test.support
Tkinter tkinter
tkFileDialog tkinter.filedialog
urllib / urllib2 urllib, urllib.parse, urllib.error, urllib.response, urllib.request, urllib.robotparser

Einige Module wurden sogar von Dateien in Bibliotheken konvertiert. Nehmen Sie als Beispiel tkinter und urllib von oben.

Kompatibilität

Wenn Sie die Kompatibilität zwischen den Versionen Python 2.x und 3.x beibehalten, können Sie das future externe Paket verwenden , um das Importieren von Standard-Bibliothekspaketen der obersten Ebene mit Python 3.x-Namen in Python 2.x-Versionen zu ermöglichen.

Oktalkonstanten

In Python 2 kann ein Oktal-Literal als definiert werden

>>> 0755  # only Python 2

Um Querkompatibilität zu gewährleisten, verwenden Sie

0o755  # both Python 2 and Python 3

Alle Klassen sind in Python 3 neue Klassen.

In Python 3.x alle Klassen Klassen im neuen Stil . Wenn Sie eine neue Klasse definieren, erbt Python implizit von object . Die Angabe eines object in einer class ist daher vollständig optional:

Python 3.x 3.0
class X: pass
class Y(object): pass

Beide Klassen enthalten jetzt object in ihrer mro (Methodenauflösungsreihenfolge):

Python 3.x 3.0
>>> X.__mro__
(__main__.X, object)

>>> Y.__mro__
(__main__.Y, object)

In Python 2.x Klassen standardmäßig Klassen im alten Stil. Sie erben nicht implizit vom object . Dies bewirkt , dass die Semantik von Klassen je nach unterscheiden , wenn wir ausdrücklich hinzufügen object als class :

Python 2.x 2.3
class X: pass
class Y(object): pass

Wenn wir versuchen, __mro__ von Y zu drucken, wird in diesem Fall eine ähnliche Ausgabe wie in der Python 3.x Ausgabe __mro__ :

Python 2.x 2.3
>>> Y.__mro__
(<class '__main__.Y'>, <type 'object'>)

Dies geschieht, weil wir bei der Definition von Y explizit von Objekt geerbt haben: class Y(object): pass . Für die Klasse X die nicht vom Objekt erbt, ist das __mro__ Attribut nicht vorhanden. Der Zugriff auf dieses Objekt führt zu einem AttributeError .

Um die Kompatibilität zwischen beiden Python-Versionen sicherzustellen , können Klassen mit object als Basisklasse definiert werden:

class mycls(object):
    """I am fully compatible with Python 2/3"""

Wenn __metaclass__ Variable __metaclass__ im globalen Gültigkeitsbereich auf type gesetzt ist, sind alle nachfolgend definierten Klassen in einem bestimmten Modul implizit im neuen Stil, ohne explizit von einem object erben zu müssen:

__metaclass__ = type

class mycls:
    """I am also fully compatible with Python 2/3"""

Entfernte Operatoren <> und ``, auch mit! = Und repr ()

In Python 2 ist <> ein Synonym für != ; Ebenso ist `foo` ein Synonym für repr(foo) .

Python 2.x 2.7
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
Python 3.x 3.0
>>> 1 <> 2
  File "<stdin>", line 1
    1 <> 2
       ^
SyntaxError: invalid syntax
>>> `foo`
  File "<stdin>", line 1
    `foo`
    ^
SyntaxError: invalid syntax

encode / decode to hex nicht mehr verfügbar

Python 2.x 2.7
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
Python 3.x 3.0
"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'str' object has no attribute 'decode'

b"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs

'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs

b'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# AttributeError: 'bytes' object has no attribute 'encode'

Wie in der Fehlermeldung vorgeschlagen, können Sie jedoch das codecs Modul verwenden, um dasselbe Ergebnis zu erzielen:

import codecs
codecs.decode('1deadbeef4', 'hex')
# Out: b'\x1d\xea\xdb\xee\xf4'
codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
# Out: b'1deadbeef4'

Beachten Sie, dass codecs.encode ein bytes Objekt zurückgibt. Um ein str Objekt zu erhalten, decode einfach in ASCII:

codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'

CMP-Funktion in Python 3 entfernt

In Python 3 wurde die integrierte cmp -Funktion zusammen mit der speziellen Methode __cmp__ .

Aus der Dokumentation:

Die Funktion cmp() sollte als verschwunden betrachtet werden, und die spezielle Methode __cmp__() wird nicht mehr unterstützt. Verwenden Sie __lt__() zum Sortieren, __eq__() mit __hash__() und andere umfassende Vergleiche nach Bedarf. (Wenn Sie wirklich die cmp() Funktionalität benötigen, können Sie den Ausdruck (a > b) - (a < b) als Entsprechung für cmp(a, b) .)

Darüber hinaus akzeptieren alle integrierten Funktionen, die den Parameter cmp akzeptiert haben, nur noch den Parameter für das key .

Im functools Modul gibt es auch die nützliche Funktion cmp_to_key(func) , mit der Sie eine cmp Funktion in eine key cmp Funktion konvertieren können:

Wandeln Sie eine Vergleichsfunktion im alten Stil in eine Schlüsselfunktion um. Wird mit Werkzeugen verwendet, die Schlüsselfunktionen (z. B. sorted() , min() , max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ) itertools.groupby() . Diese Funktion wird hauptsächlich als Übergangswerkzeug für Programme verwendet, die von Python 2 konvertiert werden und die Verwendung von Vergleichsfunktionen unterstützen.

Durchgesickerte Variablen im Listenverständnis

Python 2.x 2.3
x = 'hello world!'
vowels = [x for x in 'AEIOU'] 

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'   
Python 3.x 3.0
x = 'hello world!'
vowels = [x for x in 'AEIOU']

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'hello world!'

Wie aus dem Beispiel zu ersehen ist, wurde in Python 2 der Wert von x durchgesickert: Es maskierte hello world! und U ausgedruckt, da dies der letzte Wert von x als die Schleife endete.

In Python 3 x die ursprünglich definierte hello world! gedruckt hello world! , da die lokale Variable aus dem Listenverständnis keine Variablen aus dem umgebenden Bereich maskiert.

Außerdem haben weder Generatorausdrücke (in Python seit 2.5 verfügbar) noch Dictionary oder Set Comprehensions (die von Python 3 auf Python 2.7 zurückgespielt wurden) Variablen in Python 2.

Beachten Sie, dass Variablen sowohl in Python 2 als auch in Python 3 bei Verwendung einer for-Schleife in den umgebenden Bereich eindringen:

x = 'hello world!'
vowels = []
for x in 'AEIOU':
    vowels.append(x)
print(x)
# Out: 'U'

Karte()

map() ist ein integriertes Element, das zum Anwenden einer Funktion auf Elemente einer Iteration nützlich ist. In Python 2 gibt map eine Liste zurück. In Python 3 gibt map ein Kartenobjekt zurück , bei dem es sich um einen Generator handelt.

# Python 2.X
>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
>>> type(_)
>>> <class 'list'>

# Python 3.X
>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x*>
>>> type(_)
<class 'map'>

# We need to apply map again because we "consumed" the previous map....
>>> map(str, [1, 2, 3, 4, 5])
>>> list(_)
['1', '2', '3', '4', '5']

In Python 2 können Sie None als Identitätsfunktion übergeben. Dies funktioniert in Python 3 nicht mehr.

Python 2.x 2.3
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
Python 3.x 3.0
>>> list(map(None, [0, 1, 2, 3, 0, 5]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Wenn Sie in Python 2 mehr als ein iterierbares Argument übergeben, itertools.izip_longest map die kürzeren iterierbaren itertools.izip_longest mit None (ähnlich wie itertools.izip_longest ). In Python 3 stoppt die Iteration nach der kürzesten Iteration.

In Python 2:

Python 2.x 2.3
>>> map(None, [1, 2, 3], [1, 2], [1, 2, 3, 4, 5])
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

In Python 3:

Python 3.x 3.0
>>> list(map(lambda x, y, z: (x, y, z), [1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2)]

# to obtain the same padding as in Python 2 use zip_longest from itertools
>>> import itertools
>>> list(itertools.zip_longest([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

Hinweis : Verwenden Sie anstelle von map List Comprehensions, die mit Python 2/3 kompatibel sind. Ersetzen der map(str, [1, 2, 3, 4, 5]) :

>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']

filter (), map () und zip () geben Iteratoren statt Sequenzen zurück

Python 2.x 2.7

In Python 2- filter eingebaute Funktionen für map und zip eine Sequenz zurück. map und zip immer eine Liste zurück, während bei filter der Rückgabetyp vom Typ des angegebenen Parameters abhängt:

>>> s = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> s
'abc'
>>> s = map(lambda x: x * x, [0, 1, 2])
>>> s
[0, 1, 4]
>>> s = zip([0, 1, 2], [3, 4, 5])
>>> s
[(0, 3), (1, 4), (2, 5)]
Python 3.x 3.0

In Python 3 filter stattdessen map und zip Iterator:

>>> it = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> it
<filter object at 0x00000098A55C2518>
>>> ''.join(it)
'abc'
>>> it = map(lambda x: x * x, [0, 1, 2])
>>> it
<map object at 0x000000E0763C2D30>
>>> list(it)
[0, 1, 4]
>>> it = zip([0, 1, 2], [3, 4, 5])
>>> it
<zip object at 0x000000E0763C52C8>
>>> list(it)
[(0, 3), (1, 4), (2, 5)]

Da Python 2 itertools.izip gleichwertig zu Python 3 ist, wurde zip izip auf Python 3 entfernt.

Absolute / Relative Importe

In Python 3 ändert PEP 404 die Funktionsweise von Importen von Python 2. Implizite relative Importe sind in Paketen nicht mehr zulässig, und Importe from ... import * sind nur im Code auf Modulebene zulässig.

So erzielen Sie Python 3-Verhalten in Python 2:

  • Die absolute from __future__ import absolute_import kann mit from __future__ import absolute_import
  • explizite relative Importe werden anstelle impliziter relativer Importe gefördert

Zur Verdeutlichung kann ein Modul in Python 2 den Inhalt eines anderen Moduls, das sich in demselben Verzeichnis befindet, wie folgt importieren:

import foo

Beachten Sie, dass der Speicherort von foo allein durch die Importanweisung mehrdeutig ist. Von dieser Art des impliziten relativen Imports wird daher abgeraten, explizite relative Importe zu bevorzugen, die wie folgt aussehen:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

Der Punkt . erlaubt eine explizite Deklaration der Modulposition innerhalb des Verzeichnisbaums.


Mehr zu den relativen Importen

Betrachten Sie ein benutzerdefiniertes Paket namens shapes . Die Verzeichnisstruktur sieht wie folgt aus:

shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py

circle.py , square.py und triangle.py importieren alle util.py als Modul. Wie beziehen sie sich auf ein Modul auf derselben Ebene?

 from . import util # use util.PI, util.sq(x), etc

ODER

 from .util import * #use PI, sq(x), etc to call functions

Die . wird für relative Importe auf gleicher Ebene verwendet.

Betrachten Sie nun ein alternatives Layout des shapes Moduls:

shapes
├── __init__.py
|
├── circle
│   ├── __init__.py
│   └── circle.py
|
├── square
│   ├── __init__.py
│   └── square.py
|
├── triangle
│   ├── __init__.py
│   ├── triangle.py
|
└── util.py

Wie beziehen sich diese 3 Klassen nun auf util.py?

 from .. import util # use util.PI, util.sq(x), etc

ODER

 from ..util import * # use PI, sq(x), etc to call functions

Das .. wird für relative Importe auf übergeordneter Ebene verwendet. Mehr hinzufügen . s mit der Anzahl der Ebenen zwischen dem Elternteil und dem Kind.

Datei I / O

file ist in 3.x kein eingebauter Name mehr ( open funktioniert noch).

Interne Details der Datei-E / A wurden in das Standardbibliothek- io Modul verschoben, das auch die neue Heimat von StringIO :

import io
assert io.open is open # the builtin is an alias
buffer = io.StringIO()
buffer.write('hello, ') # returns number of characters written
buffer.write('world!\n')
buffer.getvalue() # 'hello, world!\n'

Der Dateimodus (Text vs. Binär) bestimmt nun den Datentyp, der durch Lesen einer Datei (und des zum Schreiben erforderlichen Typs) erzeugt wird:

with open('data.txt') as f:
    first_line = next(f)
    assert type(first_line) is str
with open('data.bin', 'rb') as f:
    first_kb = f.read(1024)
    assert type(first_kb) is bytes

Die Kodierung für Textdateien wird standardmäßig auf das gesetzt, was von locale.getpreferredencoding(False) . Um eine Kodierung explizit anzugeben, verwenden Sie den Parameter encoding das encoding :

with open('old_japanese_poetry.txt', 'shift_jis') as text:
    haiku = text.read()

Die Funktion round () ist die Funktion "break-break" und "return"

runde () krawatte brechen

In Python 2 wird round() für eine Zahl verwendet, die nahe an zwei ganzen Zahlen liegt, diejenige, die am weitesten von 0 entfernt ist. Zum Beispiel:

Python 2.x 2.7
round(1.5)  # Out: 2.0
round(0.5)  # Out: 1.0
round(-0.5)  # Out: -1.0
round(-1.5)  # Out: -2.0

In Python 3 gibt round() jedoch die gerade ganze Zahl (auch als Rundung der Bankiers bezeichnet ) zurück. Zum Beispiel:

Python 3.x 3.0
round(1.5)  # Out: 2
round(0.5)  # Out: 0
round(-0.5)  # Out: 0
round(-1.5)  # Out: -2

Die round () - Funktion folgt der halben bis geraden Rundungsstrategie , bei der halbe Zahlen auf die nächste gerade ganze Zahl round(2.5) zum Beispiel gibt round(2.5) jetzt 2 statt 3.0 zurück).

Wie in Wikipedia angegeben , wird dies auch als unverzerrte Rundung , konvergente Rundung , Statistiker-Rundung , niederländische Rundung , Gauß-Rundung oder ungerade Rundung bezeichnet .

Eine halbe bis gleichmäßige Rundung ist Teil des IEEE 754- Standards und auch der Standardrundungsmodus in Microsofts .NET.

Diese Rundungsstrategie verringert tendenziell den gesamten Rundungsfehler. Da im Durchschnitt die Anzahl der gerundeten Zahlen gleich der Anzahl der abgerundeten Zahlen ist, werden Rundungsfehler aufgehoben. Andere Rundungsmethoden tendieren eher dazu, den Durchschnittsfehler nach oben oder nach unten zu neigen.


round () Rückgabetyp

Die round() Funktion gibt einen float Typ in Python 2.7 zurück

Python 2.x 2.7
round(4.8)
# 5.0

Wenn in Python 3.0 das zweite Argument (Anzahl der Ziffern) weggelassen wird, wird ein int .

Python 3.x 3.0
round(4.8)
# 5

Richtig, Falsch und Keiner

In Python 2 sind True , False und None integrierte Konstanten. Dies bedeutet, dass es möglich ist, sie neu zuzuweisen.

Python 2.x 2.0
True, False = False, True
True   # False
False  # True

Mit Python 2.4 ist dies mit None nicht möglich.

Python 2.x 2.4
None = None  # SyntaxError: cannot assign to None

In Python 3 sind True , False und None jetzt Schlüsselwörter.

Python 3.x 3.0
True, False = False, True  # SyntaxError: can't assign to keyword

None = None  # SyntaxError: can't assign to keyword

Rückgabewert beim Schreiben in ein Dateiobjekt

Wenn Sie direkt in ein Dateihandle schreiben, wird in Python 2 None :

Python 2.x 2.3
hi = sys.stdout.write('hello world\n')
# Out: hello world
type(hi)
# Out: <type 'NoneType'>

In Python 3 wird beim Schreiben in einen Handle die Anzahl der beim Schreiben von Text geschriebenen Zeichen und die Anzahl der beim Schreiben von Bytes geschriebenen Bytes zurückgegeben:

Python 3.x 3.0
import sys

char_count = sys.stdout.write('hello world 🐍\n')
# Out: hello world 🐍
char_count
# Out: 14

byte_count = sys.stdout.buffer.write(b'hello world \xf0\x9f\x90\x8d\n')
# Out: hello world 🐍
byte_count
# Out: 17

long vs. int

In Python 2 wird jede ganze Zahl, die größer als C ssize_t ist, in den long Datentyp konvertiert, der durch ein L Suffix im Literal angegeben wird. Zum Beispiel bei einem 32-Bit-Build von Python:

Python 2.x 2.7
>>> 2**31
2147483648L
>>> type(2**31)
<type 'long'>
>>> 2**30
1073741824
>>> type(2**30)
<type 'int'>
>>> 2**31 - 1  # 2**31 is long and long - int is long
2147483647L

In Python 3 wurde jedoch der long Datentyp entfernt. egal wie groß die ganze Zahl ist, es wird eine int .

Python 3.x 3.0
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>

Klasse Boolescher Wert

Python 2.x 2.7

Wenn Sie in Python 2 einen booleschen Klassenwert selbst definieren möchten, müssen Sie die __nonzero__ Methode in Ihrer Klasse implementieren. Der Wert ist standardmäßig True.

class MyClass:
    def __nonzero__(self):
        return False

my_instance = MyClass()
print bool(MyClass)       # True
print bool(my_instance)   # False
Python 3.x 3.0

In Python 3 wird __bool__ anstelle von __nonzero__

class MyClass:
    def __bool__(self):
        return False

my_instance = MyClass()
print(bool(MyClass))       # True
print(bool(my_instance))   # False


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow