Sök…


Introduktion

Till skillnad från de flesta språk stöder Python två huvudversioner. Sedan 2008 när Python 3 släpptes har många gjort övergången, medan många inte har gjort det. För att förstå båda täcker detta avsnitt de viktiga skillnaderna mellan Python 2 och Python 3.

Anmärkningar

Det finns för närvarande två versioner av Python som stöds: 2.7 (Python 2) och 3.6 (Python 3). Dessutom får versionerna 3.3 och 3.4 säkerhetsuppdateringar i källformat.

Python 2.7 är bakåtkompatibel med de flesta tidigare versioner av Python och kan köra Python-kod från de flesta 1.x- och 2.x-versioner av Python oförändrade. Det är allmänt tillgängligt med en omfattande samling paket. Det anses också vara avskrivet av CPython-utvecklarna och får endast säkerhets- och bug-fix-utveckling. CPython-utvecklarna avser att överge denna version av språket 2020 .

Enligt Python Enhancement-förslag 373 finns det inga planerade framtida utgivningar av Python 2 efter den 25 juni 2016, men bugfixar och säkerhetsuppdateringar stöds fram till 2020. (Det anger inte vilket exakta datum 2020 som ska vara solnedgången för Python 2.)

Python 3 bröt avsiktligt bakåtkompatibilitet, för att ta itu med de problem som språkutvecklarna hade med kärnan i språket. Python 3 får ny utveckling och nya funktioner. Det är versionen av språket som språkutvecklarna tänker gå vidare med.

Under tiden mellan den första utgåvan av Python 3.0 och den aktuella versionen, backades vissa funktioner i Python 3 tillbaka till Python 2.6, och andra delar av Python 3 utvidgades för att ha syntax kompatibel med Python 2. Därför är det möjligt att skriva Python som fungerar på både Python 2 och Python 3 genom att använda framtida import och specialmoduler (som sex ).

Framtida import måste vara i början av din modul:

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

För mer information om __future__ modulen, se relevant sida i Python-dokumentationen .

Verktyget 2to3 är ett Python-program som konverterar Python 2.x-kod till Python 3.x-kod, se även Python-dokumentationen .

Paketet sex ger verktyg för Python 2/3-kompatibilitet:

  • enhetlig åtkomst till döpt namn på bibliotek
  • variabler för sträng- / unicodtyper
  • funktioner för metod som har tagits bort eller har bytt namn

En referens för skillnader mellan Python 2 och Python 3 kan hittas här .

Skriv ut uttalande kontra utskriftsfunktion

I Python 2 är print ett uttalande:

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)"

I Python 3 är print() en funktion med sökordargument för vanliga användningar:

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)"

Utskriftsfunktionen har följande parametrar:

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

sep är det som skiljer de objekt du skickar för att skriva ut. Till exempel:

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

end är vad slutet på utskriften sägs av. Till exempel:

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

Skriva ut igen efter en utskrift som inte slutar skriva ut på samma linje kommer att skrivas ut på samma rad:

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

Obs! För framtida kompatibilitet, print är en funktion även i Python 2.6 och framåt; men det kan inte användas om tolkning av print uttalande är inaktiverad med

from __future__ import print_function

Denna funktion har exakt samma format som Python 3: er, förutom att den saknar flush .

Se PEP 3105 för motivering.

Strängar: Bytes kontra Unicode

Python 2.x 2.7

I Python 2 finns det två varianter av strängar: de som är gjorda av byte med typ ( str ) och de som är gjorda av text med typ ( unicode ).

I Python 2 är ett objekt av typen str alltid en bytesekvens, men används vanligtvis för både text och binär data.

En strängbokstavlig tolkas som en bytsträng.

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

Det finns två undantag: Du kan definiera en Unicode-bokstav (text) uttryckligen genom att prefixera den bokstavliga med u :

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

Alternativt kan du ange att en hel moduls strängbokstäver ska skapa Unicode (text) bokstäver:

from __future__ import unicode_literals

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

För att kontrollera om din variabel är en sträng (antingen Unicode eller en byte-sträng) kan du använda:

isinstance(s, basestring)
Python 3.x 3.0

I Python 3 är str typen en Unicode-texttyp.

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

Dessutom har Python 3 lagt till ett bytes , lämpligt för binära "klumpar" eller skrivning till kodningsoberoende filer. För att skapa ett byteobjekt kan du prefix b till en strängbokstav eller kalla strängens encode :

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

För att testa om ett värde är en sträng använder du:

isinstance(s, str)
Python 3.x 3.3

Det är också möjligt att prefixera strängbokstäver med ett u prefix för att underlätta kompatibiliteten mellan kodbaserna Python 2 och Python 3. Eftersom, i Python 3, alla strängar är Unicode som standard, förbereda en sträng bokstavlig med u har ingen effekt:

u'Cafe' == 'Cafe'

Python 2: s råa Unicode-strängprefix ur stöds dock inte:

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

Observera att du måste encode ett Python 3-textobjekt ( str ) för att konvertera det till en bytes av den texten. Standardkodningen för denna metod är UTF-8 .

Du kan använda decode att fråga ett bytes för vilken Unicode-text den representerar:

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

Medan bytes finns i både Python 2 och 3, existerar unicode bara i Python 2. För att använda Python 3: s implicita Unicode-strängar i Python 2, lägg till följande till toppen av din kodfil:

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

En annan viktig skillnad är att indexering av byte i Python 3 resulterar i en int utgång som så:

b"abc"[0] == 97

Medan skivning i en storlek resulterar i ett längd 1 byte-objekt:

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

Dessutom fixar Python 3 något ovanligt beteende med unicode, dvs att byta bytsträngar i Python 2. Till exempel löses följande problem :

# -*- 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

Heltalsuppdelning

Standard division symbol ( / ) arbetar på olika sätt i Python 3 och Python 2 när den appliceras till heltal.

När du delar ett heltal med ett annat heltal i Python 3, representerar delningsoperationen x / y en sann uppdelning (använder metoden __truediv__ ) och ger ett resultat med flytande punkter. Samtidigt representerar samma operation i Python 2 en klassisk uppdelning som avrunder resultatet ned mot negativ oändlighet (även känd som att ta ordet ).

Till exempel:

Koda Python 2-utgång Python 3-utgång
3 / 2 1 1,5
2 / 3 0 ,6666666666666666
-3 / 2 -2 -1,5

Uppförandet av avrundningen mot noll avskrivs i Python 2.2 , men förblir i Python 2.7 för bakåtkompatibilitet och togs bort i Python 3.

Obs: För att få ett flottörresultat i Python 2 (utan golvrundning) kan vi ange en av operanderna med decimalpunkten. Ovanstående exempel på 2/3 som ger 0 i Python 2 ska användas som 2 / 3.0 eller 2.0 / 3 eller 2.0/3.0 att få 0.6666666666666666

Koda Python 2-utgång Python 3-utgång
3.0 / 2.0 1,5 1,5
2 / 3.0 ,6666666666666666 ,6666666666666666
-3.0 / 2 -1,5 -1,5

Det finns också golvdelningsoperatören ( // ), som fungerar på samma sätt i båda versionerna: den avrundas till närmaste heltal. (även om en flottör returneras när den används med flottörer) I båda versionerna kartlägger // operatören till __floordiv__ .

Koda Python 2-utgång Python 3-utgång
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 kan uttryckligen verkställa verklig division eller golvdelning med hjälp av inbyggda funktioner i operator :

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

Även om det är tydligt och tydligt kan det vara tråkigt att använda operatörsfunktioner för varje division. Att ändra beteendet hos / operatören föredras ofta. En vanlig praxis är att eliminera typiskt uppdelningsbeteende genom att lägga till from __future__ import division som det första uttalandet i varje modul:

# needs to be the first statement in a module
from __future__ import division
Koda Python 2-utgång Python 3-utgång
3 / 2 1,5 1,5
2 / 3 ,6666666666666666 ,6666666666666666
-3 / 2 -1,5 -1,5

from __future__ import division garanterar att / operatören representerar verklig division och endast inom modulerna som innehåller __future__ import, så det finns inga tvingande skäl för att inte aktivera den i alla nya moduler.

Obs : Vissa andra programmeringsspråk använder avrundning mot noll (trunkering) snarare än avrundning mot negativ oändlighet som Python gör (dvs. på dessa språk -3 / 2 == -1 ). Detta beteende kan skapa förvirring vid porting eller jämförelse av kod.


Obs om flottöroperander : Som ett alternativ till from __future__ import division kan man använda den vanliga divisionssymbolen / och se till att åtminstone en av operandema är en flottör: 3 / 2.0 == 1.5 . Detta kan dock betraktas som dålig praxis. Det är alldeles för enkelt att skriva average = sum(items) / len(items) och glömma att kasta ett av argumenten att flyta. Dessutom kan sådana fall ofta undvika meddelande under testning, t.ex. om du testar på en matris som innehåller float men får en mängd int under produktion. Om samma kod används i Python 3 fungerar dessutom program som förväntar sig att 3/2 3 / 2 == 1 är sant inte korrekt.

Se PEP 238 för mer detaljerade skäl till varför divisionsoperatören byttes i Python 3 och varför division i gammal stil bör undvikas.


Se ämnet Simple Math för mer om uppdelning.

Minska är inte längre en inbyggd

I Python 2 finns reduce tillgänglig antingen som en inbyggd funktion eller från functools (version 2.6 och framåt), medan i Python 3 reduce finns tillgänglig från functools . Men syntaxen för reduce i både Python2 och Python3 är densamma och reduce(function_to_reduce, list_to_reduce) .

Låt oss som exempel överväga att reducera en lista till ett enda värde genom att dela vart och ett av de angränsande siffrorna. Här använder vi truediv funktion från operator .

I Python 2.x är det så enkelt som:

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

I Python 3.x blir exemplet lite mer komplicerat:

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

Vi kan också använda from functools import reduce att undvika att ringa reduce med namnområdet.

Skillnader mellan intervall- och xrange-funktioner

I Python 2, range returnerar funktionen en lista medan xrange skapar en speciell xrange objekt, vilket är en oföränderlig sekvens, som till skillnad från andra inbyggda sekvenstyper, inte stödskivning och har varken index eller count metoder:

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

I Python 3 xrange till range , vilket nu skapar ett range . Det finns ingen 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

Dessutom, eftersom Python 3.2 range stöder också skivning, index och 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

Fördelen med att använda en speciell sekvenstyp istället för en lista är att tolkaren inte behöver tilldela minne för en lista och fylla i den:

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)

Eftersom det senare beteendet i allmänhet är önskvärt, togs det förstnämnda bort i Python 3. Om du fortfarande vill ha en lista i Python 3 kan du helt enkelt använda list() -konstruktören på ett range :

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

Kompatibilitet

För att bibehålla kompatibiliteten mellan både Python 2.x och Python 3.x versioner kan du använda builtins modulen från det externa paketets future att uppnå både framåtkompatibilitet och bakåtkompatibilitet :

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

range i future bibliotek stöder skärning, index och count i alla Python-versioner, precis som den inbyggda metoden på Python 3.2+.

Packa upp Iterables

Python 3.x 3.0

I Python 3 kan du packa upp en iterable utan att veta det exakta antalet objekt i det, och till och med ha en variabel som håller slutet på iterable. För detta tillhandahåller du en variabel som kan samla en lista med värden. Detta görs genom att placera en asterisk före namnet. Till exempel, packa upp en 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

Obs! När du använder syntaxen *variable -variabel är variable alltid en lista, även om originaltypen inte var en lista. Det kan innehålla noll eller fler element beroende på antalet element i originallistan.

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

På liknande sätt packa upp en str :

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

Exempel på att packa upp ett date ; _ Används i detta exempel som en slit och släng variabel (vi är intresserade endast i year värde):

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

Det är värt att nämna att eftersom * äter upp ett variabelt antal objekt kan du inte ha två * s för samma iterable i ett uppdrag - det skulle inte veta hur många element som går in i den första uppackningen och hur många i den andra :

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

Hittills har vi diskuterat uppackning i uppdrag. * och ** förlängdes i Python 3.5 . Det är nu möjligt att ha flera uppackningsoperationer i ett uttryck:

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

Det är också möjligt att packa upp en iterable till funktionsargument:

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

Uppackning av en ordlista använder två angränsande stjärnor ** ( PEP 448 ):

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

Detta möjliggör både åsidosättande av gamla värden och sammanslagning av ordböcker.

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 har tagit bort tupeluppackning i funktioner. Följaktligen fungerar inte följande i Python 3

# 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

Se PEP 3113 för detaljerad motivering.

Att höja och hantera undantag

Detta är Python 2-syntaxen, notera kommatecken ,raise och except linjer:

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

I Python 3, den , är syntaxen tappas och ersattes med parentes och as nyckelord:

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

För bakåtkompatibilitet är Python 3-syntaxen också tillgänglig i Python 2.6 och framåt, så den bör användas för all ny kod som inte behöver vara kompatibel med tidigare versioner.


Python 3.x 3.0

Python 3 lägger också till undantagskedjor , där du kan signalera att något annat undantag var orsaken till detta undantag. Till exempel

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

Undantaget som tas upp i except är av typen DatabaseError , men det ursprungliga undantaget markeras som attributet __cause__ för det undantaget. När spårningen visas kommer det ursprungliga undantaget också att visas i spårningen:

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')

Om du kastar in ett except utan uttrycklig kedja:

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

Traceback är

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

Ingen av dem stöds i Python 2.x; det ursprungliga undantaget och dess spårning kommer att förloras om ett annat undantag tas upp i undantagsblocket. Följande kod kan användas för kompatibilitet:

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

För att "glömma" det tidigare kastade undantaget använder du raise from None

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

Nu skulle spårningen helt enkelt vara

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

Eller för att göra den kompatibel med både Python 2 och 3 kan du använda sex paket så här:

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

.nästa () -metod på iteratorer som bytt namn

I Python 2 kan en iterator korsas genom att använda en metod som kallas next på själva iteratorn:

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

I Python 3 har .next metoden bytt namn till .__next__ , vilket bekräftar dess ”magiska” roll, så att ringa .next kommer att höja ett AttributeError . Det rätta sättet att komma åt denna funktionalitet i både Python 2 och Python 3 är att ringa next funktion med iteratorn som ett argument.

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

Den här koden är bärbar mellan versioner från 2.6 till nuvarande utgåvor.

Jämförelse av olika typer

Python 2.x 2.3

Objekt av olika typer kan jämföras. Resultaten är godtyckliga, men konsekventa. De beställs så att None är mindre än något annat, numeriska typer är mindre än icke-numeriska typer, och allt annat beställs leksikografiskt efter typ. Således är en int mindre än en str och en tuple är större än en 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

Detta gjordes ursprungligen så att en lista med blandade typer kunde sorteras och objekt skulle grupperas tillsammans efter typ:

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

Ett undantag tas upp när man jämför olika (icke-numeriska) typer:

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()

För att sortera blandade listor i Python 3 efter typer och för att uppnå kompatibilitet mellan versioner måste du ange en nyckel till den sorterade funktionen:

>>> 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}]

str använder str som key konverteras varje objekt till en sträng endast för att jämföra. Därefter ser strängrepresentationen börja med antingen [ , ' , { eller 0-9 och den kan sortera dessa (och alla följande tecken).

Användarinmatning

I Python 2 accepteras raw_input funktionen raw_input ,

Python 2.x 2.3
user_input = raw_input()

I Python 3 accepteras användarinmatning med hjälp av input .

Python 3.x 3.0
user_input = input()

I Python 2, den input kommer funktionen att acceptera input och tolka den. Även om detta kan vara användbart, har det flera säkerhetshänsyn och togs bort i Python 3. För att få tillgång till samma funktionalitet kan eval(input()) användas.

För att hålla ett skript bärbart över de två versionerna kan du sätta koden nedan nära toppen av ditt Python-skript:

try:
    input = raw_input
except NameError:
    pass

Ordboksmetod ändras

I Python 3 är många av ordboksmetoderna helt annorlunda i beteende än Python 2, och många har också tagits bort: has_key , iter* och view* är borta. I stället för d.has_key(key) , som länge hade försvunnit, måste man nu använda key in d .

I Python 2, ordlista metoder keys , values och items returnerar listor. I Python 3 returnerar de visningsobjekt istället; utsiktsobjekten är inte iteratorer, och de skiljer sig från dem på två sätt, nämligen:

  • de har storlek (man kan använda len funktionen på dem)
  • de kan upprepas under många gånger

Dessutom, liksom med iteratorer, återspeglas förändringarna i ordboken i visningsobjekten.

Python 2.7 har backporterat dessa metoder från Python 3; de är tillgängliga som viewkeys , viewvalues och viewitems . För att omvandla Python 2-kod till Python 3-kod är motsvarande former:

  • d.keys() , d.values() och d.items() i Python 2 bör ändras till list(d.keys()) , list(d.values()) och list(d.items())
  • d.iterkeys() , d.itervalues() och d.iteritems() bör ändras till iter(d.keys()) , eller ännu bättre, iter(d) ; iter(d.values()) respektive iter(d.items())
  • och slutligen Python 2.7-metoden kallar d.viewkeys() , d.viewvalues() och d.viewitems() kan ersättas med d.keys() , d.values() och d.items() .

Porting av Python 2-kod som iterates över ordbordsnycklar, värden eller objekt medan du muterar den är ibland svår. Överväga:

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

Koden ser ut som om det skulle fungera på samma sätt i Python 3, men där keys metoden returnerar en vy objekt, inte en lista, och om ordboken ändrar storlek samtidigt som upprepas över kommer Python 3-koden krasch med RuntimeError: dictionary changed size during iteration . Lösningen är naturligtvis att skriva ordentligt for key in list(d) .

På liknande sätt uppträder visningsobjekt på ett annorlunda sätt än iteratorer: man kan inte använda next() på dem och man kan inte återuppta iterationen; det skulle istället starta om; om Python 2-koden skickar returvärdet för d.iterkeys() , d.itervalues() eller d.iteritems() till en metod som förväntar sig en iterator istället för en iterable , bör det vara iter(d) , iter(d.values()) eller iter(d.items()) i Python 3.

exec-uttalande är en funktion i Python 3

I Python 2 är exec ett uttalande med speciell syntax: exec code [in globals[, locals]]. I Python 3 är exec nu en funktion: exec(code, [, globals[, locals]]) , och Python 2-syntaxen kommer att höja en SyntaxError .

När print ändrades från uttalande till en funktion, lades också en __future__ import till. Det finns dock inget from __future__ import exec_function , eftersom det inte behövs: exec-uttalandet i Python 2 kan också användas med syntax som ser exakt ut som exec funktionen kallas i Python 3. Således kan du ändra påståenden

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

till former

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

och de senare formerna garanteras att fungera identiskt i både Python 2 och Python 3.

hasattr-funktionsfel i Python 2

I Python 2, när en egenskap tar upp ett fel, kommer hasattr att ignorera den här egenskapen och returnera 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

Det här felet fixas i Python3. Så om du använder Python 2, använd

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

eller använd getattr istället

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

Byt namn på moduler

Några moduler i standardbiblioteket har fått nytt namn:

Gammalt namn Nytt namn
_winreg winreg
ConfigParser configparser
copy_reg copyreg
SocketServer socketserver
_markupbase markupbase
repr reprlib
test.test_support test.support
Tkinter Tkinter
tkFileDialog tkinter.filedialog
urllib / urllib2 urllib, urllib.parse, urllib.error, urllib.response, urllib.request, urllib.robotparser

Vissa moduler har till och med konverterats från filer till bibliotek. Ta tkinter och urllib ovanifrån som ett exempel.

Kompatibilitet

När du bibehåller kompatibiliteten mellan både Python 2.x- och 3.x-versionerna kan du använda det future externa paketet för att möjliggöra import av högsta standardbibliotekspaket med Python 3.x-namn i Python 2.x-versionerna.

Octal Constants

I Python 2 kan en oktal literal definieras som

>>> 0755  # only Python 2

Använd för att säkerställa tvärkompatibilitet

0o755  # both Python 2 and Python 3

Alla klasser är "klasser i ny stil" i Python 3.

I Python 3.x alla klasser i nya stilklasser ; när man definierar en ny klasspython implicit gör det arv från object . Som sådana, som specificerar object i en class definition är en helt valfri:

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

Båda dessa klasser innehåller nu object i sin mro ( mro ):

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

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

I Python 2.x klasser som standard gamla klasser; de ärver inte implicit från object . Detta medför semantiken av klasser att variera beroende på om vi lägger uttryckligen object som bas class :

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

I det här fallet, om vi försöker skriva ut __mro__ för Y , kommer en liknande utgång som i Python 3.x fallet att visas:

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

Detta händer eftersom vi uttryckligen fick Y ärva från objektet när vi definierade det: class Y(object): pass . För klass X som inte ärver från objektet finns inte __mro__ attributet, försöker komma åt det resulterar i ett AttributeError .

För att säkerställa kompatibilitet mellan båda versionerna av Python kan klasser definieras med object som en basklass:

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

Alternativt, om variabeln __metaclass__ är inställd på type i global omfattning, är alla efterföljande definierade klasser i en given modul implicit nystil utan att behöva uttryckligen ärva från object :

__metaclass__ = type

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

Borttagna operatörer <> och ``, synonymt med! = Och repr ()

I Python 2 är <> en synonym för != ; På samma sätt är `foo` en 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

kodning / avkodning till hex är inte längre tillgänglig

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'

Som föreslagits av felmeddelandet kan du dock använda codecs modulen för att uppnå samma resultat:

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'

Observera att codecs.encode returnerar ett bytes . För att få ett str objekt decode bara till ASCII:

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

cmp-funktion tas bort i Python 3

I Python 3 cmp inbyggda cmp -funktionen ut tillsammans med __cmp__ specialmetod.

Från dokumentationen:

cmp() ska behandlas som försvunnen och __cmp__() specialmetoden stöds inte längre. Använd __lt__() för sortering, __eq__() med __hash__() och andra rika jämförelser efter behov. (Om du verkligen behöver cmp() -funktionen kan du använda uttrycket (a > b) - (a < b) som ekvivalent för cmp(a, b) .)

Dessutom accepterar alla inbyggda funktioner som accepterade cmp parametern nu bara parametern key nyckelord endast.

I functools modulen finns också användbar cmp_to_key(func) funktion cmp_to_key(func) som låter dig konvertera från en cmp stil-funktion till en key stil-funktion:

Förvandla en gammal stil jämförelsefunktion till en nyckelfunktion. Används med verktyg som accepterar nyckelfunktioner (som sorted() , min() , max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ). Denna funktion används främst som ett övergångsverktyg för program som konverteras från Python 2 som stöder användningen av jämförelsefunktioner.

Läckta variabler i listförståelse

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!'

Som framgår av exemplet, i Python 2 läckte värdet på x : det maskerade hello world! och tryckte U , eftersom detta var det sista värdet på x när slingan slutade.

I Python 3 x skrivs emellertid den ursprungligen definierade hello world! , eftersom den lokala variabeln från listförståelsen inte maskerar variabler från det omgivande omfånget.

Dessutom läcker varken generatoruttryck (tillgängliga i Python sedan 2,5) eller ordböcker eller uppsättningsförståelser (som backporterades till Python 2.7 från Python 3) variabler i Python 2.

Observera att i både Python 2 och Python 3 kommer variabler att läcka ut i det omgivande omfånget när du använder en for loop:

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

Karta()

map() är en inbyggd som är användbar för att tillämpa en funktion på delar av en iterable. I Python 2 returnerar map en lista. I Python 3, map returnerar ett kartobjekt, som är en generator.

# 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']

I Python 2 kan du passera None att fungera som en identitetsfunktion. Detta fungerar inte längre i Python 3.

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

Dessutom, när du passerar mer än en iterable som argument i Python 2, map de kortare iterablesna med None (liknande itertools.izip_longest ). I Python 3 slutar iterationen efter den kortaste iterbara.

I 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)]

I 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)]

Obs : istället för map överväga att använda listförståelser, som är Python 2/3 kompatibla. Byt ut map(str, [1, 2, 3, 4, 5]) :

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

filter (), karta () och zip () returnerar iteratorer istället för sekvenser

Python 2.x 2.7

I Python 2- filter map och zip inbyggda funktioner en sekvens. map och zip returnerar alltid en lista medan med filter är returtypen beroende på typen av given parameter:

>>> 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

I Python 3- filter returnerar iterator för map och zip returer istället:

>>> 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)]

Sedan Python 2 itertools.izip är ekvivalent med Python 3 zip izip har tagits bort på Python 3.

Absolut / relativ import

I Python 3 ändrar PEP 404 hur import fungerar från Python 2. Implicit relativ import är inte längre tillåten i paket och from ... import * import är endast tillåtet i modulnivåkod.

För att uppnå Python 3-beteende i Python 2:

  • funktionen för absolutimport kan aktiveras med from __future__ import absolute_import
  • uttrycklig relativ import uppmuntras i stället för implicit relativimport

För förtydligande kan en modul i Python 2 importera innehållet i en annan modul som finns i samma katalog enligt följande:

import foo

Observera att foo platsen är tvetydig endast från importmeddelandet. Denna typ av implicit relativimport avskräckas således till förmån för uttrycklig relativimport , som ser ut enligt följande:

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

Punkten . tillåter en uttrycklig deklaration av modulplatsen i katalogträdet.


Mer om relativ import

Tänk på något användardefinierat paket som kallas shapes . Katalogstrukturen är som följer:

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

circle.py , square.py och triangle.py all import util.py som modul. Hur hänvisar de till en modul på samma nivå?

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

ELLER

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

Den . används för relativ import på samma nivå.

Tänk nu på en alternativ layout för shapes :

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

Nu, hur kommer dessa tre klasser att hänvisa till util.py?

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

ELLER

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

Det .. används för relativa import förälder-nivå. Lägg till mer . s med antal nivåer mellan förälder och barn.

Fil I / O

file är inte längre ett inbyggt namn i 3.x ( open fungerar fortfarande).

Interna detaljer för fil I / O har flyttats till standardbibliotekets io modul, som också är det nya hemmet för 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'

Filläget (text kontra binärt) bestämmer nu vilken typ av data som produceras genom att läsa en fil (och vilken typ som krävs för att skriva):

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

Kodningen för textfiler går som standard tillbaka till locale.getpreferredencoding(False) . För att specificera en kodning uttryckligen använder du encoding :

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

Den runda () -funktionen slips- och returtyp

rund () slips

I Python 2 kommer att använda round() på ett nummer lika nära två heltal att returnera det som är längst från 0. Till exempel:

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

I Python 3 kommer round() att returnera det jämna heltalet (även bankers avrundning ). Till exempel:

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

Funktionen runda () följer halv till jämn rundningsstrategi som kommer att runda halvvägsnummer till närmaste jämna heltal (till exempel ger round(2.5) nu 2 istället för 3.0).

Enligt referens på Wikipedia är detta också känt som opartisk avrundning , konvergent avrundning , statistikens avrundning , holländsk avrundning , Gaussisk avrundning eller udda jämn avrundning .

Halva till jämna avrundning är en del av IEEE 754- standarden och det är också standardavrundningsläget i Microsofts .NET.

Denna avrundningsstrategi tenderar att minska det totala avrundningsfelet. Eftersom antalet nummer som avrundas i genomsnitt är detsamma som antalet som avrundas avbryter avrundningsfel. Andra avrundningsmetoder tenderar istället att ha en uppåt eller nedåt förspänning i det genomsnittliga felet.


round () returtyp

Funktionen round() returnerar en float i Python 2.7

Python 2.x 2.7
round(4.8)
# 5.0

Från Python 3.0, om det andra argumentet (antal siffror) utelämnas, returnerar det ett int .

Python 3.x 3.0
round(4.8)
# 5

Det är sant, falskt och inget

I Python 2 är True , False och None inbyggda konstanter. Vilket innebär att det är möjligt att tilldela dem igen.

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

Du kan inte göra detta med None sedan Python 2.4.

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

I Python 3 är True , False och None nu nyckelord.

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

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

Returnera värde när du skriver till ett filobjekt

I Python 2 returnerar skrivning direkt till ett filhandtag None :

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

I Python 3 kommer att skriva till ett handtag att returnera antalet tecken skrivna när du skriver text och antalet byte skrivna när du skriver byte:

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

lång kontra int

I Python 2 skulle alla heltal som är större än en C- ssize_t omvandlas till den long datatypen, indikerat med en L suffix på bokstaven. Till exempel på en 32-bitars byggnad av 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

I Python 3 togs dock den long datatypen bort; oavsett hur stort heltalet är, kommer det att vara ett int .

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

Booleskt värde

Python 2.x 2.7

Om du vill definiera ett booleskt värde i Python 2 måste du implementera metoden __nonzero__ din klass. Värdet är sant som standard.

class MyClass:
    def __nonzero__(self):
        return False

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

I Python 3 används __bool__ istället för __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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow