Vad är nytt i Python 3.1¶
- Författare:
Raymond Hettinger
I den här artikeln förklaras de nya funktionerna i Python 3.1 jämfört med 3.0. Python 3.1 släpptes den 27 juni 2009.
PEP 372: Ordnade ordböcker¶
Vanliga Python-ordböcker itererar över nyckel/värde-par i godtycklig ordning. Under årens lopp har ett antal författare skrivit alternativa implementationer som kommer ihåg den ordning som nycklarna ursprungligen infogades. Baserat på erfarenheterna från dessa implementationer har en ny collections.OrderedDict
-klass introducerats.
OrderedDict API är i stort sett detsamma som vanliga ordböcker men kommer att iterera över nycklar och värden i en garanterad ordning beroende på när en nyckel först infogades. Om en ny post skriver över en befintlig post lämnas den ursprungliga inmatningspositionen oförändrad. Om du tar bort en post och lägger in den igen flyttas den till slutet.
Standardbiblioteket stöder nu användning av ordnade lexikon i flera moduler. Modulen configparser
använder dem som standard. Detta gör att konfigurationsfiler kan läsas, ändras och sedan skrivas tillbaka i sin ursprungliga ordning. Metoden _asdict() för collections.namedtuple()
returnerar nu en ordnad ordbok där värdena visas i samma ordning som de underliggande tuple-indexen. Modulen json
håller på att byggas ut med en object_pairs_hook för att OrderedDicts ska kunna byggas av avkodaren. Stöd har även lagts till för tredjepartsverktyg som PyYAML.
Se även
- PEP 372 - Ordnade ordböcker
PEP skriven av Armin Ronacher och Raymond Hettinger. Implementation skriven av Raymond Hettinger.
Eftersom en ordnad ordbok kommer ihåg sin inmatningsordning kan den användas tillsammans med sortering för att skapa en sorterad ordbok:
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
De nya sorterade lexikonen behåller sin sorteringsordning när poster raderas. Men när nya nycklar läggs till, läggs nycklarna till i slutet och sorteringen bibehålls inte.
PEP 378: Formatspecifikator för tusentalsavgränsare¶
Den inbyggda funktionen format()
och metoden str.format()
använder ett minispråk som nu innehåller ett enkelt, icke-lokalanpassat sätt att formatera ett tal med en tusentalsavgränsare. Det ger ett sätt att humanisera ett programs utdata, förbättra dess professionella utseende och läsbarhet:
>>> format(1234567, ',d')
'1,234,567'
>>> format(1234567.89, ',.2f')
'1,234,567.89'
>>> format(12345.6 + 8901234.12j, ',f')
'12,345.600000+8,901,234.120000j'
>>> format(Decimal('1234567.89'), ',f')
'1,234,567.89'
De typer som stöds är int
, float
, complex
och decimal.decimal
.
Diskussioner pågår om hur man ska ange alternativa avgränsare som punkter, mellanslag, apostrofer eller understrykningstecken. Lokalt anpassade program bör använda den befintliga formatspecificeraren n som redan har visst stöd för tusentals separatorer.
Se även
- PEP 378 - Formatspecifikator för tusentalsavgränsare
PEP skriven av Raymond Hettinger och implementerad av Eric Smith och Mark Dickinson.
Andra språkliga förändringar¶
Några mindre ändringar som gjorts i Python-språkets kärna är:
Kataloger och zip-arkiv som innehåller en
__main__.py
-fil kan nu exekveras direkt genom att namnet anges till tolken. Katalogen/zipfilen infogas automatiskt som den första posten i sys.path. (Förslag och ursprunglig patch av Andy Chu; reviderad patch av Phillip J. Eby och Nick Coghlan; bpo-1739468.)Typen
int()
har en metodbit_length
som returnerar det antal bitar som krävs för att representera argumentet i binärformat:>>> n = 37 >>> bin(37) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(Bidrag från Fredrik Johansson, Victor Stinner, Raymond Hettinger och Mark Dickinson; bpo-3439.)
Fälten i
format()
-strängar kan nu numreras automatiskt:>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
Tidigare skulle strängen ha krävt numrerade fält som t.ex:
'Sir {0} av {1}'
.(Bidrag från Eric Smith; bpo-5237.)
Funktionen
string.maketrans()
är utdaterad och ersätts av nya statiska metoder,bytes.maketrans()
ochbytearray.maketrans()
. Den här ändringen löser förvirringen kring vilka typer som stöds av modulenstring
. Nu harstr
,bytes
ochbytearray
var och en sina egna maketrans- och translate-metoder med mellanliggande översättningstabeller av lämplig typ.(Bidrag från Georg Brandl; bpo-5675.)
Syntaxen för
with
-satsen tillåter nu flera kontexthanterare i en enda sats:>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
Med den nya syntaxen behövs inte längre funktionen
contextlib.nested()
och den är nu föråldrad.(Bidrag från Georg Brandl och Mattias Brändström; appspot issue 53094.)
round(x, n)
returnerar nu ett heltal om x är ett heltal. Tidigare returnerade den en float:>>> round(1123, -2) 1100
(Bidrag från Mark Dickinson; bpo-4707.)
Python använder nu David Gays algoritm för att hitta den kortaste representationen av flyttal som inte ändrar sitt värde. Detta bör bidra till att mildra en del av förvirringen kring binära flyttal.
Betydelsen är lätt att se med ett tal som
1,1
som inte har någon exakt motsvarighet i binär flyttal. Eftersom det inte finns någon exakt motsvarighet utvärderas ett uttryck somfloat('1.1')
till det närmaste representerbara värdet, vilket är0x1.199999999999ap+0
i hex eller1.100000000000000088817841970012523233890533447265625
i decimal. Det närmaste värdet användes och används fortfarande i efterföljande beräkningar med flyttal.Det som är nytt är hur numret visas. Tidigare använde Python ett enkelt tillvägagångssätt. Värdet av
repr(1.1)
beräknades somformat(1.1, '.17g')
vilket utvärderades till'1.1000000000000001'
. Fördelen med att använda 17 siffror var att den förlitade sig på IEEE-754-garantier för att säkerställa atteval(repr(1.1))
skulle avrundas exakt till sitt ursprungliga värde. Nackdelen är att många tyckte att resultatet var förvirrande (och misstog de inneboende begränsningarna i binär representation av flyttal som ett problem med Python självt).Den nya algoritmen för
repr(1.1)
är smartare och returnerar'1.1'
. I själva verket söker den efter alla likvärdiga strängrepresentationer (de som lagras med samma underliggande flottörvärde) och returnerar den kortaste representationen.Den nya algoritmen tenderar att ge renare representationer när det är möjligt, men den ändrar inte de underliggande värdena. Så det är fortfarande så att
1,1 + 2,2 != 3,3
även om representationerna kan antyda något annat.Den nya algoritmen är beroende av vissa funktioner i den underliggande implementeringen av flyttal. Om de nödvändiga funktionerna inte finns kommer den gamla algoritmen att fortsätta att användas. Dessutom säkerställer text pickle-protokollen portabilitet mellan plattformar genom att använda den gamla algoritmen.
(Bidrag från Eric Smith och Mark Dickinson; bpo-1580)
Nya, förbättrade och utfasade moduler¶
Lagt till en
collections.Counter
-klass för att stödja bekväm räkning av unika objekt i en sekvens eller iterabel:>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(Bidrag från Raymond Hettinger; bpo-1696199.)
Lagt till en ny modul,
tkinter.ttk
för åtkomst till Tk:s tematiska widgetuppsättning. Grundtanken med ttk är att i möjligaste mån separera koden som implementerar en widgets beteende från koden som implementerar dess utseende.(Bidrag från Guilherme Polo; bpo-2983.)
Klasserna
gzip.GzipFile
ochbz2.BZ2File
har nu stöd för kontexthanteringsprotokollet:>>> # Automatically close file after writing >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Bidrag från Antoine Pitrou.)
Modulen
decimal
stöder nu metoder för att skapa ett decimalobjekt från ett binärtfloat
. Konverteringen är exakt men kan ibland vara överraskande:>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
Det långa decimalresultatet visar det faktiska binära bråket som lagras för 1,1. Bråket har många siffror eftersom 1,1 inte kan representeras exakt i binär form.
(Bidrag från Raymond Hettinger och Mark Dickinson.)
Modulen
itertools
har utökats med två nya funktioner. Funktionenitertools.combinations_with_replacement()
är en av fyra funktioner för att generera kombinatorik, inklusive permutationer och kartesiska produkter. Funktionenitertools.compress()
efterliknar sin namne från APL. Dessutom har den befintliga funktionenitertools.count()
nu ett valfritt step-argument och kan acceptera alla typer av räknesekvenser, inklusivefractions.Fraction
ochdecimal.Decimal
:>>> [p+q for p,q in combinations_with_replacement('LOVE', 2)] ['LL', 'LO', 'LV', 'LE', 'OO', 'OV', 'OE', 'VV', 'VE', 'EE'] >>> list(compress(data=range(10), selectors=[0,0,1,1,0,1,0,1,0,0])) [2, 3, 5, 7] >>> c = count(start=Fraction(1,2), step=Fraction(1,6)) >>> [next(c), next(c), next(c), next(c)] [Fraction(1, 2), Fraction(2, 3), Fraction(5, 6), Fraction(1, 1)]
(Bidrag från Raymond Hettinger.)
collections.namedtuple()
har nu stöd för ett nyckelordsargument rename som gör att ogiltiga fältnamn automatiskt kan konverteras till positionsnamn i formen _0, _1, etc. Detta är användbart när fältnamnen skapas av en extern källa, t.ex. ett CSV-huvud, en SQL-fältlista eller användarinmatning:>>> query = input() SELECT region, dept, count(*) FROM main GROUPBY region, dept >>> cursor.execute(query) >>> query_fields = [desc[0] for desc in cursor.description] >>> UserQuery = namedtuple('UserQuery', query_fields, rename=True) >>> pprint.pprint([UserQuery(*row) for row in cursor]) [UserQuery(region='South', dept='Shipping', _2=185), UserQuery(region='North', dept='Accounting', _2=37), UserQuery(region='West', dept='Sales', _2=419)]
(Bidrag från Raymond Hettinger; bpo-1818.)
Funktionerna
re.sub()
,re.subn()
ochre.split()
accepterar nu en flags parameter.(Bidrag från Gregory Smith.)
Modulen
logging
implementerar nu en enkel klasslogging.NullHandler
för applikationer som inte använder loggning men som anropar bibliotekskod som gör det. Genom att konfigurera en null-hanterare kan man undvika onödiga varningar som ”Inga hanterare kunde hittas för logger foo”:>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Bidrag från Vinay Sajip; bpo-4384).
Modulen
runpy
, som stöder kommandoradsväxeln-m
, stöder nu exekvering av paket genom att leta efter och exekvera en__main__
-undermodul när ett paketnamn anges.(Bidrag från Andi Vajda; bpo-4195.)
Modulen
pdb
kan nu komma åt och visa källkod som laddats viazipimport
(eller någon annan kompatibel PEP 302-laddare).(Bidrag från Alexander Belopolsky; bpo-4201.)
functools.partial
-objekt kan nu picklas.
(Föreslagen av Antoine Pitrou och Jesse Noller. Implementerad av Jack Diederich; bpo-5228.)
Lägg till
pydoc
-hjälpämnen för symboler så atthelp('@')
fungerar som förväntat i den interaktiva miljön.(Bidrag från David Laban; bpo-4739.)
Modulen
unittest
har nu stöd för att hoppa över enskilda tester eller klasser av tester. Den stöder även att markera ett test som ett förväntat misslyckande, ett test som man vet är trasigt, men som inte bör räknas som ett misslyckande i ett TestResult:klass TestGizmo(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("win")), "kräver Windows") def test_gizmo_on_windows(self): ... @unittest.expectedFailure def test_gimzo_without_required_library(self): ...
Dessutom har tester för undantag byggts ut för att fungera med kontexthanterare som använder
with
statement:def test_division_by_zero(self): med self.assertRaises(ZeroDivisionError): x / 0
Dessutom har flera nya assertionmetoder lagts till, inklusive
assertSetEqual()
,assertDictEqual()
,assertDictContainsSubset()
,assertListEqual()
,assertTupleEqual()
,assertSequenceEqual()
,assertRaisesRegexp()
,assertIsNone()
, ochassertIsNotNone()
.(Bidrag från Benjamin Peterson och Antoine Pitrou.)
Modulen
io
har tre nya konstanter för metodenseek()
:SEEK_SET
,SEEK_CUR
ochSEEK_END
.Tupeln
sys.version_info
är nu en namngiven tupel:>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(Bidrag från Ross Light; bpo-4285.)
Modulerna
nntplib
ochimaplib
har nu stöd för IPv6.Modulen
pickle
har anpassats för bättre interoperabilitet med Python 2.x när den används med protokoll 2 eller lägre. Omorganiseringen av standardbiblioteket ändrade den formella referensen för många objekt. Till exempel kallas__builtin__.set
i Python 2 förbuiltins.set
i Python 3. Denna förändring förvirrade ansträngningarna att dela data mellan olika versioner av Python. Men nu när protokoll 2 eller lägre väljs, kommer picklern automatiskt att använda de gamla Python 2-namnen för både laddning och dumpning. Denna remappning är aktiverad som standard men kan avaktiveras med alternativet fix_imports:>>> s = {1, 2, 3} >>> pickle.dumps(s, protocol=0) b'c__builtin__\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.' >>> pickle.dumps(s, protocol=0, fix_imports=False) b'cbuiltins\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.'
En olycklig men oundviklig bieffekt av denna förändring är att protokoll 2-pickles som produceras av Python 3.1 inte kommer att kunna läsas med Python 3.0. Det senaste pickle-protokollet, protokoll 3, bör användas vid migrering av data mellan Python 3.x-implementeringar, eftersom det inte försöker förbli kompatibelt med Python 2.x.
(Bidrag från Alexandre Vassalotti och Antoine Pitrou, bpo-6137.)
En ny modul,
importlib
har lagts till. Den ger en komplett, portabel, ren Python-referensimplementation avimport
-satsen och dess motsvarighet, funktionen__import__()
. Den utgör ett stort steg framåt när det gäller att dokumentera och definiera de åtgärder som vidtas under import.(Bidrag från Brett Cannon.)
Optimeringar¶
Stora prestandaförbättringar har lagts till:
Det nya I/O-biblioteket (enligt definitionen i PEP 3116) var till största delen skrivet i Python och visade sig snabbt vara en problematisk flaskhals i Python 3.0. I Python 3.1 har I/O-biblioteket skrivits om helt och hållet i C och är 2 till 20 gånger snabbare beroende på vilken uppgift som ska utföras. Den rena Python-versionen är fortfarande tillgänglig för experimentändamål genom modulen
_pyio
.(Bidrag från Amaury Forgeot d’Arc och Antoine Pitrou.)
Lagt till en heuristik som gör att tuples och dicts som bara innehåller objekt som inte kan spåras inte spåras av skräpsamlaren. Detta kan minska storleken på samlingarna och därmed sopinsamlingens overhead i långkörande program, beroende på hur datatyperna används.
(Bidrag från Antoine Pitrou, bpo-4688.)
Genom att aktivera ett konfigurationsalternativ med namnet
--with-computed-gotos
på kompilatorer som stöder det (särskilt: gcc, SunPro, icc), kompileras bytecode-utvärderingsslingan med en ny dispatchmekanism som ger hastigheter på upp till 20%, beroende på system, kompilator och benchmark.(Bidrag från Antoine Pitrou tillsammans med ett antal andra deltagare, bpo-4753).
Avkodningen av UTF-8, UTF-16 och LATIN-1 är nu två till fyra gånger snabbare.
(Bidrag från Antoine Pitrou och Amaury Forgeot d’Arc, bpo-4868.)
Modulen
json
har nu ett C-tillägg som avsevärt förbättrar dess prestanda. Dessutom har API:et modifierats så att json endast fungerar medstr
, inte medbytes
. Denna förändring gör att modulen nära matchar JSON-specifikationen som definieras i termer av Unicode.(Bidrag från Bob Ippolito och konverterad till Py3.1 av Antoine Pitrou och Benjamin Peterson; bpo-4136.)
Unpickling internerar nu attributnamnen för picklade objekt. Detta sparar minne och gör att pickles kan vara mindre.
(Bidrag från Jake McGuire och Antoine Pitrou; bpo-5084.)
IDLE¶
IDLE:s formatmeny innehåller nu ett alternativ för att ta bort efterföljande blanksteg från en källfil.
(Bidrag från Roger D. Serwy; bpo-5150.)
Ändringar i Build och C API¶
Ändringar i Pythons byggprocess och i C API inkluderar:
Heltal lagras nu internt antingen i basen
2**15
eller i basen2**30
, basen bestäms vid byggtiden. Tidigare lagrades de alltid i bas2**15
. Att använda bas2**30
ger betydande prestandaförbättringar på 64-bitars maskiner, men benchmarkresultaten på 32-bitars maskiner har varit blandade. Därför är standardinställningen att använda bas2**30
på 64-bitars maskiner och bas2**15
på 32-bitars maskiner; på Unix finns det ett nytt configure-alternativ--enable-big-digits
som kan användas för att åsidosätta denna standardinställning.Bortsett från prestandaförbättringarna bör denna ändring vara osynlig för slutanvändarna, med ett undantag: för test- och felsökningsändamål finns det en ny
sys.int_info
som ger information om det interna formatet, med antalet bitar per siffra och storleken i byte på den C-typ som används för att lagra varje siffra:>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(Bidrag från Mark Dickinson; bpo-4258.)
Funktionen
PyLong_AsUnsignedLongLong()
hanterar nu en negativ pylong genom att geOverflowError
istället förTypeError
.(Bidrag från Mark Dickinson och Lisandro Dalcrin; bpo-5175.)
Föråldrad
PyNumber_Int()
. AnvändPyNumber_Long()
istället.(Bidrag från Mark Dickinson; bpo-4910.)
Lagt till en ny
PyOS_string_to_double()
-funktion för att ersätta de föråldrade funktionernaPyOS_ascii_strtod()
ochPyOS_ascii_atof()
.(Bidrag från Mark Dickinson; bpo-5914.)
Lagt till
PyCapsule
som en ersättning förPyCObject
API. Den huvudsakliga skillnaden är att den nya typen har ett väldefinierat gränssnitt för att skicka information om typningssäkerhet och en mindre komplicerad signatur för att anropa en destruktor. Den gamla typen hade ett problematiskt API och är nu föråldrad.(Bidrag från Larry Hastings; bpo-5630.)
Portning till Python 3.1¶
I det här avsnittet listas tidigare beskrivna ändringar och andra buggfixar som kan kräva ändringar i din kod:
De nya representationerna av strängar med flyttal kan bryta befintliga doctests. Till exempel:
def e(): '''Compute the base of natural logarithms. >>> e() 2.7182818284590451 ''' return sum(1/math.factorial(x) for x in reversed(range(30))) doctest.testmod() ********************************************************************** Failed example: e() Expected: 2.7182818284590451 Got: 2.718281828459045 **********************************************************************
Den automatiska namnomvandlingen i pickle-modulen för protokoll 2 eller lägre kan göra Python 3.1-pickles oläsliga i Python 3.0. En lösning är att använda protokoll 3. En annan lösning är att sätta alternativet fix_imports till
False
. Se diskussionen ovan för mer information.