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 metod bit_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() och bytearray.maketrans(). Den här ändringen löser förvirringen kring vilka typer som stöds av modulen string. Nu har str, bytes och bytearray 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 som float('1.1') till det närmaste representerbara värdet, vilket är 0x1.199999999999ap+0 i hex eller 1.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 som format(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 att eval(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 och bz2.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ärt float. 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. Funktionen itertools.combinations_with_replacement() är en av fyra funktioner för att generera kombinatorik, inklusive permutationer och kartesiska produkter. Funktionen itertools.compress() efterliknar sin namne från APL. Dessutom har den befintliga funktionen itertools.count() nu ett valfritt step-argument och kan acceptera alla typer av räknesekvenser, inklusive fractions.Fraction och decimal.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() och re.split() accepterar nu en flags parameter.

    (Bidrag från Gregory Smith.)

  • Modulen logging implementerar nu en enkel klass logging.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 via zipimport (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å att help('@') 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(), och assertIsNotNone().

    (Bidrag från Benjamin Peterson och Antoine Pitrou.)

  • Modulen io har tre nya konstanter för metoden seek(): SEEK_SET, SEEK_CUR och SEEK_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 och imaplib har nu stöd för IPv6.

    (Bidrag från Derek Morr; bpo-1655 och bpo-1664.)

  • 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ör builtins.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 av import-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 med str, inte med bytes. 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 basen 2**30, basen bestäms vid byggtiden. Tidigare lagrades de alltid i bas 2**15. Att använda bas 2**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 bas 2**30 på 64-bitars maskiner och bas 2**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 ge OverflowError istället för TypeError.

    (Bidrag från Mark Dickinson och Lisandro Dalcrin; bpo-5175.)

  • Föråldrad PyNumber_Int(). Använd PyNumber_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 funktionerna PyOS_ascii_strtod() och PyOS_ascii_atof().

    (Bidrag från Mark Dickinson; bpo-5914.)

  • Lagt till PyCapsule som en ersättning för PyCObject 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.