Python Language
Inkompatibilitäten von Python 2 zu Python 3
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:
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:
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
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)
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)
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é'
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'
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:
>>> 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:
>>> 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:
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:
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:
# 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
:
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:
#forward-compatible
from builtins import range
for i in range(10**8):
pass
#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
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
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}
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
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 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:
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 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')
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")
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:
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.
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
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)]
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.
user_input = raw_input()
Während in Python 3 eine Benutzereingabe unter Verwendung der akzeptierten input
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()
undd.items()
von Python 2 sollten inlist(d.keys())
,list(d.values())
undlist(d.items())
-
d.iterkeys()
,d.itervalues()
undd.iteritems()
sollten initer(d.keys())
oder noch besseriter(d)
geändert werden.iter(d.values())
bzw.iter(d.items())
- und schließlich kann die Methode Python 2.7
d.viewkeys()
,d.viewvalues()
undd.viewitems()
durchd.keys()
,d.values()
undd.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
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars
zu formen
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:
class X: pass
class Y(object): pass
Beide Klassen enthalten jetzt object
in ihrer mro
(Methodenauflösungsreihenfolge):
>>> 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
:
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__
:
>>> 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)
.
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
>>> 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
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
"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 diecmp()
Funktionalität benötigen, können Sie den Ausdruck(a > b) - (a < b)
als Entsprechung fürcmp(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
x = 'hello world!'
vowels = [x for x in 'AEIOU']
print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'
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.
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
>>> 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:
>>> 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:
>>> 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
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)]
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 mitfrom __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:
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:
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
round(4.8)
# 5.0
Wenn in Python 3.0 das zweite Argument (Anzahl der Ziffern) weggelassen wird, wird ein int
.
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.
True, False = False, True
True # False
False # True
Mit Python 2.4 ist dies mit None
nicht möglich.
None = None # SyntaxError: cannot assign to None
In Python 3 sind True
, False
und None
jetzt Schlüsselwörter.
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
:
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:
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:
>>> 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
.
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>
Klasse Boolescher Wert
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
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