Vad är nytt i Python 2.4

Författare:

A.M. Kuchling

I den här artikeln beskrivs de nya funktionerna i Python 2.4.1, som släpptes den 30 mars 2005.

Python 2.4 är en medelstor release. Den introducerar inte lika många förändringar som den radikala Python 2.2, men introducerar fler funktioner än den konservativa 2.3-versionen. De mest betydande nya språkfunktionerna är funktionsdekoratorer och generatoruttryck; de flesta andra ändringar är i standardbiblioteket.

Enligt CVS-ändringsloggarna tillämpades 481 korrigeringar och 502 buggar åtgärdades mellan Python 2.3 och 2.4. Båda siffrorna är sannolikt underskattningar.

Den här artikeln försöker inte ge en fullständig specifikation av varje enskild ny funktion, utan ger istället en kort introduktion till varje funktion. För fullständiga detaljer bör du hänvisa till dokumentationen för Python 2.4, till exempel Python Library Reference och Python Reference Manual. Ofta kommer du att hänvisas till PEP för en viss ny funktion för förklaringar av implementeringen och designrationaliteten.

PEP 218: Inbyggda set-objekt

Python 2.3 introducerade modulen sets. C-implementeringar av set-datatyper har nu lagts till i Python-kärnan som två nya inbyggda typer, set(iterable) och frozenset(iterable). De ger höghastighetsoperationer för medlemskapstestning, för att eliminera dubbletter från sekvenser och för matematiska operationer som unioner, korsningar, skillnader och symmetriska skillnader:

>>> a = set('abracadabra')              # form a set from a string
>>> 'z' in a                            # fast membership testing
False
>>> a                                   # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a)                          # convert back into a string
'arbcd'

>>> b = set('alacazam')                 # form a second set
>>> a - b                               # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b                               # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b                               # letters in both a and b
set(['a', 'c'])
>>> a ^ b                               # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])

>>> a.add('z')                          # add a new element
>>> a.update('wxy')                     # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x')                       # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])

Typen frozenset() är en oföränderlig version av set(). Eftersom den är oföränderlig och hashbar kan den användas som en nyckel i en ordbok eller som en del av en annan uppsättning.

Modulen sets finns kvar i standardbiblioteket och kan vara användbar om du vill underordna klasserna Set eller ImmutableSet. Det finns för närvarande inga planer på att avskriva modulen.

Se även

PEP 218 - Lägga till en inbyggd objekttyp för set

Ursprungligen föreslagen av Greg Wilson och slutligen implementerad av Raymond Hettinger.

PEP 237: Förenande av långa heltal och heltal

Den långa övergångsprocessen för denna PEP, som påbörjades i Python 2.2, tar ytterligare ett steg framåt i Python 2.4. I 2.3 utlöste vissa heltalsoperationer som skulle bete sig annorlunda efter int/long-unifiering FutureWarning-varningar och returnerade värden begränsade till 32 eller 64 bitar (beroende på din plattform). I 2.4 ger dessa uttryck inte längre någon varning utan ger istället ett annat resultat som vanligtvis är ett långt heltal.

De problematiska uttrycken är främst vänsterskift och långa hexadecimal- och oktalkonstanter. Till exempel resulterar 2 << 32 i en varning i 2.3, som utvärderas till 0 på 32-bitars plattformar. I Python 2.4 returnerar detta uttryck nu det korrekta svaret, 8589934592.

Se även

PEP 237 - Unifiera långa heltal och heltal

Ursprunglig PEP skriven av Moshe Zadka och GvR. Ändringarna för 2.4 implementerades av Kalle Svensson.

PEP 289: Generatoruttryck

Iteratorfunktionen som introducerades i Python 2.2 och modulen itertools gör det lättare att skriva program som loopar genom stora datamängder utan att ha hela datamängden i minnet på en gång. Listkomprehensioner passar inte in i den här bilden särskilt bra eftersom de producerar ett Python-listobjekt som innehåller alla objekt. Detta drar oundvikligen alla objekt till minnet, vilket kan vara ett problem om din datauppsättning är mycket stor. När man försöker skriva ett program i funktionell stil skulle det vara naturligt att skriva något i stil med:

links = [link for link in get_all_links() if not link.followed]
för länk i länkar:
    ...

istället för

för länk i get_all_links():
    om länk.följd:
        fortsätt
    ...

Den första formen är mer kortfattad och kanske mer läsbar, men om du har att göra med ett stort antal länkobjekt måste du skriva den andra formen för att undvika att ha alla länkobjekt i minnet samtidigt.

Generatoruttryck fungerar på samma sätt som listkomprehensioner men materialiserar inte hela listan; istället skapar de en generator som returnerar elementen ett efter ett. Exemplet ovan kan skrivas som:

länkar = (länk för länk i get_all_links() if not link.followed)
för länk i länkar:
    ...

Generatoruttryck måste alltid skrivas inom parentes, som i exemplet ovan. Parentesen som signalerar ett funktionsanrop räknas också, så om du vill skapa en iterator som omedelbart skickas till en funktion kan du skriva:

print sum(obj.count för obj i list_all_objects())

Generatoruttryck skiljer sig från listkomprehensioner på flera små sätt. Det mest anmärkningsvärda är att loopvariabeln (obj i exemplet ovan) inte är tillgänglig utanför generatoruttrycket. Listförståelser lämnar variabeln tilldelad till sitt senaste värde; framtida versioner av Python kommer att ändra detta, vilket gör att listförståelser matchar generatoruttryck i detta avseende.

Se även

PEP 289 - Generatoruttryck

Föreslagen av Raymond Hettinger och implementerad av Jiwon Seo med tidiga insatser styrda av Hye-Shik Chang.

PEP 292: Enklare strängbyten

Några nya klasser i standardbiblioteket ger en alternativ mekanism för att ersätta variabler med strängar; denna typ av ersättning kan vara bättre för applikationer där otränade användare behöver redigera mallar.

Det vanliga sättet att ersätta variabler med namn är operatorn %:

>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'

När man skriver mallsträngen kan det vara lätt att glömma i eller s efter den avslutande parentesen. Det här är inte ett stort problem om mallen finns i en Python-modul, eftersom du kör koden, får ett ”Unsupported format character” ValueError och åtgärdar problemet. Men tänk på en applikation som Mailman där mallsträngar eller översättningar redigeras av användare som inte känner till Python-språket. Formatsträngens syntax är komplicerad att förklara för sådana användare, och om de gör ett misstag är det svårt att ge dem användbar feedback.

PEP 292 lägger till en Template-klass till string-modulen som använder $ för att ange en substitution:

>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'

Om en nyckel saknas i ordlistan kommer metoden substitute() att ge upphov till ett KeyError. Det finns också en safe_substitute()-metod som ignorerar saknade nycklar:

>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'

Se även

PEP 292 - Enklare ersättningar för strängar

Skriven och implementerad av Barry Warsaw.

PEP 318: Dekoratorer för funktioner och metoder

Python 2.2 utökade Pythons objektmodell genom att lägga till statiska metoder och klassmetoder, men det utökade inte Pythons syntax för att ge något nytt sätt att definiera statiska metoder eller klassmetoder. Istället var du tvungen att skriva en def-sats på vanligt sätt och skicka den resulterande metoden till en staticmethod()- eller classmethod()-funktion som skulle packa upp funktionen som en metod av den nya typen. Din kod skulle se ut så här:

klass C:
   def meth (cls):
       ...

   meth = classmethod(meth) # Återkoppla namn till inplastad klassmetod

Om metoden var mycket lång skulle det vara lätt att missa eller glömma classmethod()-inkallelsen efter funktionskroppen.

Avsikten var alltid att lägga till en syntax för att göra sådana definitioner mer läsbara, men vid tidpunkten för 2.2:s release var en bra syntax inte självklar. I dag är en bra syntax fortfarande inte självklar, men användarna efterfrågar enklare tillgång till funktionen; en ny syntaktisk funktion har lagts till för att tillgodose detta behov.

Den nya funktionen kallas ”funktionsdekoratorer”. Namnet kommer från idén att classmethod(), staticmethod() och vänner lagrar ytterligare information om ett funktionsobjekt; de dekorerar funktioner med mer detaljer.

Notationen är hämtad från Java och använder tecknet '@' som indikator. Med hjälp av den nya syntaxen skulle exemplet ovan skrivas:

class C:

   @classmethod
   def meth (cls):
       ...

@classmethod är en förkortning för uppgiften meth=classmethod(meth). Mer generellt, om du har följande:

@A
@B
@C
def f ():
    ...

Det motsvarar följande kod före inredningen:

def f(): ...
f = A(B(C(f)))

Dekoratorer måste komma på raden före en funktionsdefinition, en dekorator per rad, och kan inte vara på samma rad som def-satsen, vilket innebär att @A def f(): ... är olagligt. Du kan bara dekorera funktionsdefinitioner, antingen på modulnivå eller inuti en klass; du kan inte dekorera klassdefinitioner.

En dekorator är bara en funktion som tar den funktion som ska dekoreras som argument och returnerar antingen samma funktion eller något nytt objekt. Returvärdet för dekoratorn behöver inte vara anropsbart (även om det vanligtvis är det), såvida inte ytterligare dekoratorer kommer att tillämpas på resultatet. Det är lätt att skriva egna dekoratorer. Följande enkla exempel sätter bara ett attribut på funktionsobjektet:

>>> def deco(func):
...    func.attr = 'decorated'
...    return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>

Som ett lite mer realistiskt exempel kontrollerar följande dekorator att det medföljande argumentet är ett heltal:

def require_int (func):
    def wrapper (arg):
        assert isinstance(arg, int)
        return func(arg)

    returnera omslag

@kräv_int
def p1 (arg):
    skriv ut arg

@krav_int
def p2(arg):
    skriv ut arg*2

Ett exempel i PEP 318 innehåller en finare version av denna idé som låter dig både ange den nödvändiga typen och kontrollera den returnerade typen.

Dekoratorfunktioner kan ta argument. Om argument anges anropas din dekoratorfunktion med endast dessa argument och måste returnera en ny dekoratorfunktion; denna funktion måste ta en enda funktion och returnera en funktion, enligt tidigare beskrivning. Med andra ord, @A @B @C(args) blir:

def f(): ...
_deco = C(args)
f = A(B(_deco(f)))

Att få till det här kan vara en smula klurigt, men det är inte särskilt svårt.

En liten relaterad förändring gör attributet func_name för funktioner skrivbart. Detta attribut används för att visa funktionsnamn i spårningar, så dekoratorer bör ändra namnet på alla nya funktioner som konstrueras och returneras.

Se även

PEP 318 - Dekoratorer för funktioner, metoder och klasser

Skriven av Kevin D. Smith, Jim Jewett och Skip Montanaro. Flera personer skrev patchar som implementerade funktionsdekoratorer, men den som faktiskt checkades in var patch #979728, skriven av Mark Russell.

https://wiki.python.org/moin/PythonDecoratorLibrary

Denna Wiki-sida innehåller flera exempel på dekoratorer.

PEP 322: Omvänd iteration

En ny inbyggd funktion, reversed(seq), tar en sekvens och returnerar en iterator som loopar över elementen i sekvensen i omvänd ordning.

>>> for i in reversed(xrange(1,4)):
...    print i
...
3
2
1

Jämfört med utökad skivning, t.ex. range(1,4)[::-1], är reversed() lättare att läsa, körs snabbare och använder betydligt mindre minne.

Observera att reversed() endast accepterar sekvenser, inte godtyckliga iteratorer. Om du vill vända en iterator måste du först konvertera den till en lista med list().

>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
...   print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
  ...

Se även

PEP 322 - Omvänd iteration

Skriven och implementerad av Raymond Hettinger.

PEP 324: Ny delprocess Modul

Standardbiblioteket tillhandahåller ett antal sätt att exekvera en subprocess, med olika funktioner och olika komplexitetsnivåer. os.system(command) är lätt att använda, men långsam (den kör en skalprocess som exekverar kommandot) och farlig (du måste vara försiktig med att escapa skalets metatecken). Modulen popen2 erbjuder klasser som kan fånga standardutdata och standardfel från subprocessen, men namngivningen är förvirrande. Modulen subprocess rensar upp detta och ger ett enhetligt gränssnitt som erbjuder alla funktioner du kan behöva.

Istället för popen2:s samling av klasser innehåller subprocess en enda klass som heter subprocess.Popen vars konstruktor stöder ett antal olika nyckelordsargument.

class Popen(args, bufsize=0, körbar=None,
            stdin=None, stdout=None, stderr=None,
            preexec_fn=None, close_fds=False, shell=False,
            cwd=Ingen, env=Ingen, universal_newlines=False,
            startupinfo=None, creationflags=0):

args är vanligen en sekvens av strängar som kommer att vara argumenten till det program som körs som subprocess. (Om argumentet shell är sant kan args vara en sträng som sedan skickas vidare till skalet för tolkning, precis som os.system() gör)

stdin, stdout och stderr anger vad subprocessens in-, ut- och felströmmar ska vara. Du kan ange ett filobjekt eller en filbeskrivare, eller så kan du använda konstanten subprocess.PIPE för att skapa en pipe mellan subprocessen och den överordnade processen.

Konstruktören har ett antal praktiska alternativ:

  • close_fds begär att alla filbeskrivare stängs innan subprocessen körs.

  • cwd anger den arbetskatalog i vilken subprocessen ska köras (standard är den överordnade processens arbetskatalog).

  • env är en ordbok som anger miljövariabler.

  • preexec_fn är en funktion som anropas innan barnet startas.

  • universal_newlines öppnar barnets in- och utdata med hjälp av Pythons universal newlines-funktion.

När du har skapat instansen Popen kan du anropa dess metod wait() för att pausa tills subprocessen har avslutats, poll() för att kontrollera om den har avslutats utan paus, eller communicate(data) för att skicka strängen data till subprocessens standardinmatning. communicate(data) läser sedan alla data som underprocessen har skickat till sin standardutgång eller standardfel, och returnerar en tupel (stdout_data, stderr_data).

call() är en genväg som skickar sina argument till Popen-konstruktören, väntar på att kommandot ska slutföras och returnerar statuskoden för underprocessen. Den kan fungera som en säkrare motsvarighet till os.system():

sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
    # Framgång
    ...
else:
    # dpkg returnerade ett fel
    ...

Kommandot anropas utan användning av skalet. Om du verkligen vill använda skalet kan du lägga till shell=True som ett nyckelordsargument och ange en sträng i stället för en sekvens:

sts = subprocess.call('dpkg -i /tmp/nytt-paket.deb', shell=True)

PEP:en tar olika exempel på shell- och Python-kod och visar hur de skulle kunna översättas till Python-kod som använder subprocess. Att läsa detta avsnitt av PEP rekommenderas starkt.

Se även

PEP 324 - subprocess - Ny processmodul

Skriven och implementerad av Peter Åstrand, med hjälp av bland andra Fredrik Lundh.

PEP 327: Decimal datatyp

Python har alltid haft stöd för flyttal (FP), baserat på den underliggande C double-typen, som datatyp. Men även om de flesta programmeringsspråk tillhandahåller en flyttalstyp, är många människor (även programmerare) omedvetna om att flyttal inte representerar vissa decimalfraktioner korrekt. Den nya typen Decimal kan representera dessa fraktioner korrekt, upp till en användarspecificerad precisionsgräns.

Varför behövs Decimal?

Begränsningarna härrör från den representation som används för flyttal. FP-tal består av tre komponenter:

  • Tecknet, som är positivt eller negativt.

  • Mantissan, som är ett ensiffrigt binärt tal följt av en bråkdel. Till exempel är 1,01 i bas-2-notation 1 + 0/2 + 1/4, eller 1,25 i decimalnotation.

  • Exponenten, som anger var decimaltecknet är placerat i det representerade talet.

Till exempel har talet 1,25 positivt tecken, ett mantissavärde på 1,01 (i binär) och en exponent på 0 (decimaltecknet behöver inte flyttas). Talet 5 har samma tecken och mantissa, men exponenten är 2 eftersom mantissan multipliceras med 4 (2 i potens med exponenten 2); 1,25 * 4 är lika med 5.

Moderna system har vanligtvis stöd för flyttal som följer en standard som kallas IEEE 754. C:s typ double implementeras vanligtvis som ett 64-bitars IEEE 754-tal, som använder 52 bitars utrymme för mantissan. Detta innebär att tal endast kan specificeras med 52 bitars precision. Om du försöker representera tal vars expansion upprepas i det oändliga, avbryts expansionen efter 52 bitar. Tyvärr måste de flesta programvaror producera utdata i bas 10, och vanliga bråk i bas 10 är ofta upprepade decimaler i binär. Till exempel är 1,1 decimal binär 1,0001100110011 ...; .1 = 1/16 + 1/32 + 1/256 plus ett oändligt antal ytterligare termer. IEEE 754 måste hugga bort den oändligt upprepade decimalen efter 52 siffror, så representationen är något felaktig.

Ibland kan du se denna felaktighet när numret skrivs ut:

>>> 1.1
1.1000000000000001

Felaktigheten syns inte alltid när du skriver ut talet eftersom konverteringen av FP till decimalsträng tillhandahålls av C-biblioteket, och de flesta C-bibliotek försöker producera förnuftig utdata. Även om det inte visas, finns felaktigheten fortfarande kvar och efterföljande operationer kan förstora felet.

För många tillämpningar spelar detta ingen roll. Om jag plottar punkter och visar dem på min bildskärm är skillnaden mellan 1,1 och 1,1000000000000001 för liten för att synas. Rapporter begränsar ofta utdata till ett visst antal decimaler och om man avrundar till två, tre eller till och med åtta decimaler syns aldrig felet. För applikationer där det spelar roll är det dock mycket arbete att implementera egna aritmetiska rutiner.

Därför skapades typen Decimal.

Typen Decimal

En ny modul, decimal, har lagts till i Pythons standardbibliotek. Den innehåller två klasser, Decimal och Context. Decimal-instanser representerar tal, och Context-instanser används för att sammanfatta olika inställningar som precision och standardavrundningsläge.

Decimal-instanser är oföränderliga, precis som vanliga heltal och FP-tal i Python; när de väl har skapats kan du inte ändra det värde som en instans representerar. Decimal-instanser kan skapas från heltal eller strängar:

>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")

Du kan också ange tuples som innehåller tecknet, mantissan representerad som en tuple av decimalsiffror och exponenten:

>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")

Försiktighetsåtgärd: teckenbiten är ett booleskt värde, så 0 är positivt och 1 är negativt.

Konvertering från flyttal innebär lite av ett problem: ska FP-talet som representerar 1,1 bli decimaltalet för exakt 1,1, eller för 1,1 plus eventuella felaktigheter som införs? Beslutet blev att undvika problemet och lämna en sådan konvertering utanför API:et. Istället bör du konvertera flyttalstalet till en sträng med önskad precision och skicka strängen till Decimal-konstruktören:

>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")

När du har Decimal-instanser kan du utföra de vanliga matematiska operationerna på dem. En begränsning: exponentiering kräver en heltalsexponent:

>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
  ...
decimal.InvalidOperation: x ** (non-integer)

Du kan kombinera Decimal-instanser med heltal, men inte med flyttal:

>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
  ...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>

Decimal-tal kan användas med modulerna math och cmath, men observera att de omedelbart konverteras till flyttal innan operationen utförs, vilket kan resultera i en möjlig förlust av precision och noggrannhet. Du kommer också att få tillbaka ett vanligt flyttal och inte ett Decimal.

>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j

Decimal-instanser har en sqrt()-metod som returnerar en Decimal, men om du behöver andra saker, t.ex. trigonometriska funktioner, måste du implementera dem:

>>> d.sqrt()
Decimal("351364.1828820134592177245001")

Typen Context

Instanser av klassen Context kapslar in flera inställningar för decimaloperationer:

  • prec är precisionen, antalet decimaler.

  • rounding anger avrundningssättet. Modulen decimal har konstanter för de olika möjligheterna: ROUND_DOWN, ROUND_CEILING, ROUND_HALF_EVEN och flera andra.

  • traps är en ordbok som anger vad som händer när vissa feltillstånd inträffar: antingen uppstår ett undantag eller så returneras ett värde. Några exempel på feltillstånd är division med noll, precisionsförlust och överflöd.

Det finns en trådlokal standardkontext tillgänglig genom att anropa getcontext(); du kan ändra egenskaperna för denna kontext för att ändra standardprecision, avrundning eller trap-hantering. Följande exempel visar effekten av att ändra precisionen för standardkontexten:

>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")

Standardåtgärden för feltillstånd är valbar; modulen kan antingen returnera ett specialvärde som oändlighet eller inte ett tal, eller så kan undantag skapas:

>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
  ...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>

Instansen Context har också olika metoder för att formatera tal, t.ex. to_eng_string() och to_sci_string().

Mer information finns i dokumentationen för modulen decimal, som innehåller en snabbstartshandledning och en referens.

Se även

PEP 327 - Decimal datatyp

Skriven av Facundo Batista och implementerad av Facundo Batista, Eric Price, Raymond Hettinger, Aahz och Tim Peters.

http://www.lahey.com/float.htm

I artikeln används Fortran-kod för att illustrera många av de problem som felaktigheter i flyttal kan orsaka.

https://speleotrove.com/decimal/

En beskrivning av en decimalbaserad representation. Denna representation föreslås som en standard och ligger till grund för Pythons nya decimaltyp. Mycket av detta material har skrivits av Mike Cowlishaw, designer av Rexx-språket.

PEP 328: Import av flera linjer

En språkändring är en liten syntaktisk justering som syftar till att göra det enklare att importera många namn från en modul. I en from module import names-sats är names en sekvens av namn åtskilda med kommatecken. Om sekvensen är mycket lång kan du antingen skriva flera importer från samma modul, eller så kan du använda backslashes för att undkomma radavslutningarna så här:

from SimpleXMLRPCServer import SimpleXMLRPCServer,\
            SimpleXMLRPCRequestHandler,\
            CGIXMLRPCRequestHandler,\
            resolve_prickad_attribut

Den syntaktiska förändringen i Python 2.4 gör det helt enkelt möjligt att sätta namnen inom parentes. Python ignorerar nya rader inom ett uttryck med parenteser, så de bakre bindestrecken behövs inte längre:

from SimpleXMLRPCServer import (SimpleXMLRPCServer,
                                SimpleXMLRPCRequestHandler,
                                CGIXMLRPCRequestHandler,
                                resolve_dotted_attribute)

PEP föreslår också att alla import-satser ska vara absoluta importer, med ett inledande .-tecken för att indikera en relativ import. Denna del av PEP implementerades inte för Python 2.4, men slutfördes för Python 2.5.

Se även

PEP 328 - Import: Flera rader och absolut/relativ

Skrivet av Aahz. Import av flera rader genomfördes av Dima Dorfman.

PEP 331: Lokaloberoende omvandling av flyttal/sträng

Modulen locale låter Python-program välja olika konverteringar och visningskonventioner som är anpassade till ett visst land eller språk. Modulen var dock noga med att inte ändra den numeriska locale eftersom olika funktioner i Pythons implementation krävde att den numeriska locale skulle förbli inställd på 'C' locale. Ofta berodde detta på att koden använde C-bibliotekets funktion atof().

Att inte ställa in den numeriska språkdräkten orsakade dock problem för tillägg som använde C-bibliotek från tredje part, eftersom de inte skulle ha rätt språkdräkt inställd. Det motiverande exemplet var GTK+, vars widgetar i användargränssnittet inte visade siffror i den aktuella språkdräkten.

Lösningen som beskrivs i PEP är att lägga till tre nya funktioner i Python API som endast utför ASCII-konverteringar och ignorerar locale-inställningen:

  • PyOS_ascii_strtod(str, ptr) och PyOS_ascii_atof(str, ptr) konverterar båda en sträng till en C double.

  • PyOS_ascii_formatd(buffer, buf_len, format, d) konverterar ett double till en ASCII-sträng.

Koden för dessa funktioner kom från GLib-biblioteket (https://developer-old.gnome.org/glib/2.26/), vars utvecklare licensierade de relevanta funktionerna och donerade dem till Python Software Foundation. Modulen locale kan nu ändra den numeriska språkdräkten, så att tillägg som GTK+ ger rätt resultat.

Se även

PEP 331 - Lokaloberoende omvandling av float/sträng

Skriven av Christian R. Reis och implementerad av Gustavo Carneiro.

Andra språkliga förändringar

Här är alla ändringar som Python 2.4 gör i kärnan i Python-språket.

  • Dekoratorer för funktioner och metoder har lagts till (PEP 318).

  • Inbyggda set() och frozenset() typer har lagts till (PEP 218). Andra nya inbyggda funktioner inkluderar funktionen reversed(seq) (PEP 322).

  • Generatoruttryck har lagts till (PEP 289).

  • Vissa numeriska uttryck returnerar inte längre värden som är begränsade till 32 eller 64 bitar (PEP 237).

  • Du kan nu sätta parenteser runt listan med namn i en from module import names-sats (PEP 328).

  • Metoden dict.update() accepterar nu samma argumentformer som konstruktören dict. Detta inkluderar alla mappningar, alla iterationer av nyckel/värde-par och nyckelordsargument. (Bidrag från Raymond Hettinger.)

  • Strängmetoderna ljust(), rjust() och center() tar nu ett valfritt argument för att ange ett annat fyllnadstecken än ett mellanslag. (Bidrag från Raymond Hettinger.)

  • Strängar har också fått en rsplit()-metod som fungerar som split()-metoden men delar från slutet av strängen. (Bidrag från Sean Reifschneider.)

    >>> 'www.python.org'.split('.', 1)
    ['www', 'python.org']
    'www.python.org'.rsplit('.', 1)
    ['www.python', 'org']
    
  • Tre nyckelordsparametrar, cmp, key och reverse, lades till i metoden sort() för listor. Dessa parametrar gör vissa vanliga användningar av sort() enklare. Alla dessa parametrar är valfria.

    För parametern cmp ska värdet vara en jämförelsefunktion som tar två parametrar och returnerar -1, 0 eller +1 beroende på hur parametrarna jämförs. Denna funktion kommer sedan att användas för att sortera listan. Tidigare var detta den enda parametern som kunde anges till sort().

    key bör vara en funktion med en parameter som tar ett element i en lista och returnerar en jämförelsenyckel för elementet. Listan sorteras sedan med hjälp av jämförelsenycklarna. I följande exempel sorteras en lista utan hänsyn till fall:

    >>> L = ['A', 'b', 'c', 'D']
    >>> L.sort()                 # Case-sensitive sort
    >>> L
    ['A', 'D', 'b', 'c']
    >>> # Using 'key' parameter to sort list
    >>> L.sort(key=lambda x: x.lower())
    >>> L
    ['A', 'b', 'c', 'D']
    >>> # Old-fashioned way
    >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
    >>> L
    ['A', 'b', 'c', 'D']
    

    Det sista exemplet, där parametern cmp används, är det gamla sättet att utföra en sortering utan skiftlägeskänslighet. Det fungerar men är långsammare än att använda en key-parameter. Med key anropas lower()-metoden en gång för varje element i listan, medan den med cmp anropas två gånger för varje jämförelse, så med key sparas anrop av lower()-metoden.

    För enkla nyckelfunktioner och jämförelsefunktioner är det ofta möjligt att undvika ett lambda-uttryck genom att använda en obunden metod i stället. Till exempel skrivs ovanstående sortering utan skiftlägeskänslighet bäst som:

    >>> L.sort(key=str.lower)
    >>> L
    ['A', 'b', 'c', 'D']
    

    Slutligen tar parametern reverse ett booleskt värde. Om värdet är sant kommer listan att sorteras i omvänd ordning. Istället för L.sort(); L.reverse() kan du nu skriva L.sort(reverse=True).

    Resultatet av sorteringen är nu garanterat stabilt. Det innebär att två poster med lika nycklar returneras i samma ordning som de matades in. Du kan t.ex. sortera en lista med personer efter namn och sedan sortera listan efter ålder, vilket resulterar i en lista som är sorterad efter ålder där personer med samma ålder är i namnsorterad ordning.

    (Alla ändringar i sort() har gjorts av Raymond Hettinger.)

  • Det finns en ny inbyggd funktion sorted(iterable) som fungerar som in-place list.sort()-metoden men som kan användas i uttryck. Skillnaderna är:

  • indata kan vara vilken iterabel som helst;

  • en nybildad kopia sorteras, varvid originalet lämnas intakt; och

  • uttrycket returnerar den nya sorterade kopian

    >>> L = [9,7,8,3,2,4,1,6,5]
    >>> [10+i for i in sorted(L)]       # usable in a list comprehension
    [11, 12, 13, 14, 15, 16, 17, 18, 19]
    >>> L                               # original is left unchanged
    [9,7,8,3,2,4,1,6,5]
    >>> sorted('Monty Python')          # any iterable may be an input
    [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']
    
    >>> # List the contents of a dict sorted by key values
    >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)
    >>> for k, v in sorted(colormap.iteritems()):
    ...     print k, v
    ...
    black 4
    blue 2
    green 3
    red 1
    yellow 5
    

    (Bidrag från Raymond Hettinger.)

  • Integer-operationer kommer inte längre att utlösa en OverflowWarning. Varningen OverflowWarning kommer att försvinna i Python 2.5.

  • Tolken har fått en ny switch, -m, som tar ett namn, söker efter motsvarande modul på sys.path och kör modulen som ett skript. Till exempel kan du nu köra Python-profileraren med python -m profile. (Bidrag från Nick Coghlan.)

  • Funktionerna eval(expr, globals, locals) och execfile(filnamn, globals, locals) samt exec-satsen accepterar nu valfri mappningstyp för parametern locals. Tidigare var detta tvunget att vara en vanlig Python-ordbok. (Bidrag från Raymond Hettinger.)

  • Den inbyggda funktionen zip() och itertools.izip() returnerar nu en tom lista om de anropas utan argument. Tidigare gav de upphov till ett TypeError-undantag. Detta gör dem mer lämpade för användning med argumentlistor av varierande längd:

    >>> def transpose(array):
    ...    return zip(*array)
    ...
    >>> transpose([(1,2,3), (4,5,6)])
    [(1, 4), (2, 5), (3, 6)]
    >>> transpose([])
    []
    

    (Bidrag från Raymond Hettinger.)

  • Om ett fel uppstår vid import av en modul lämnas inte längre ett delvis initialiserat modulobjekt kvar i sys.modules. Det ofullständiga modulobjektet som lämnades kvar kunde hindra ytterligare import av samma modul från att lyckas, vilket ledde till förvirrande fel. (Åtgärdat av Tim Peters.)

  • None är nu en konstant; kod som binder ett nytt värde till namnet None är nu ett syntaxfel. (Bidrag från Raymond Hettinger.)

Optimeringar

  • De inre looparna för list- och tuple-slicing har optimerats och körs nu ungefär en tredjedel snabbare. De inre looparna för ordböcker optimerades också, vilket resulterade i prestandaökningar för keys(), values(), items(), iterkeys(), itervalues() och iteritems(). (Bidrag från Raymond Hettinger.)

  • Maskineriet för att växa och krympa listor har optimerats för hastighet och utrymmeseffektivitet. Att lägga till och plocka från listor går nu snabbare tack vare effektivare kodvägar och mindre frekvent användning av det underliggande systemet realloc(). Listförståelse gynnas också. list.extend() har också optimerats och konverterar inte längre sitt argument till en tillfällig lista innan baslistan utökas. (Bidrag från Raymond Hettinger.)

  • list(), tuple(), map(), filter() och zip() körs nu flera gånger snabbare med argument som inte är sekvenser och som innehåller metoden __len__(). (Bidrag från Raymond Hettinger.)

  • Metoderna list.__getitem__(), dict.__getitem__() och dict.__contains__() är nu implementerade som method_descriptor-objekt i stället för wrapper_descriptor-objekt. Denna form av åtkomst fördubblar deras prestanda och gör dem mer lämpliga att använda som argument till funktionaler: map(mydict.__getitem__, keylist). (Bidrag från Raymond Hettinger.)

  • Lade till en ny opcode, LIST_APPEND, som förenklar den genererade bytekoden för listförståelser och snabbar upp dem med ungefär en tredjedel. (Bidrag från Raymond Hettinger.)

  • Bytekodsoptimeraren Peephole har förbättrats för att producera kortare och snabbare bytekod; anmärkningsvärt nog är den resulterande bytekoden mer läsbar. (Förbättrad av Raymond Hettinger.)

  • Strängkonkateneringar i satser av formen s = s + "abc" och s += "abc" utförs nu mer effektivt under vissa omständigheter. Denna optimering kommer inte att finnas i andra Python-implementationer som Jython, så du bör inte förlita dig på den; att använda join()-metoden för strängar rekommenderas fortfarande när du effektivt vill limma ihop ett stort antal strängar. (Bidrag från Armin Rigo.)

Nettoresultatet av 2.4-optimeringarna är att Python 2.4 kör pystone-riktmärket cirka 5% faster än Python 2.3 och 35% faster än Python 2.2. (pystone är inte ett särskilt bra riktmärke, men det är den mest använda mätningen av Pythons prestanda. Dina egna applikationer kan visa större eller mindre fördelar med Python 2.4.)

Nya, förbättrade och utfasade moduler

Som vanligt fick Pythons standardbibliotek ett antal förbättringar och buggfixar. Här är en partiell lista över de mest anmärkningsvärda ändringarna, sorterade alfabetiskt efter modulnamn. Se filen Misc/NEWS i källträdet för en mer komplett lista över ändringar, eller titta igenom CVS-loggarna för alla detaljer.

  • Modulen asyncore:s funktion loop() har nu en parameter count som låter dig utföra ett begränsat antal genomgångar av pollingloopen. Standardinställningen är fortfarande att loopa för evigt.

  • Modulen base64 har nu mer komplett RFC 3548-stöd för Base64-, Base32- och Base16-kodning och -avkodning, inklusive valfri skiftlägesändring och valfria alternativa alfabet. (Bidrag från Barry Warsaw.)

  • Modulen bisect har nu en underliggande C-implementering för förbättrad prestanda. (Bidrag från Dmitry Vasiliev.)

  • CJKCodecs samlingar av östasiatiska codecs, som underhålls av Hye-Shik Chang, integrerades i 2.4. De nya kodningarna är:

  • Kinesiska (PRC): gb2312, gbk, gb18030, big5hkscs, hz

  • Kinesiska (ROC): big5, cp950

  • Japanska: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,

    iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004

  • Koreanska: cp949, euc-kr, johab, iso-2022-kr

  • Några andra nya kodningar har lagts till: HP Roman8, ISO_8859-11, ISO_8859-16, PCTP-154 och TIS-620.

  • UTF-8- och UTF-16-codecs klarar nu bättre av att ta emot partiell indata. Tidigare försökte klassen StreamReader att läsa mer data, vilket gjorde det omöjligt att återuppta avkodningen från strömmen. Metoden read() kommer nu att returnera så mycket data som möjligt och framtida anrop kommer att återuppta avkodningen där tidigare anrop slutade. (Implementerad av Walter Dörwald.)

  • Det finns en ny collections-modul för olika specialiserade datatyper för samlingar. För närvarande innehåller den bara en typ, deque, en kö med dubbla ändar som stöder effektivt tillägg och borttagning av element från båda ändarna:

    >>> from collections import deque
    >>> d = deque('ghi')        # make a new deque with three items
    >>> d.append('j')           # add a new entry to the right side
    >>> d.appendleft('f')       # add a new entry to the left side
    >>> d                       # show the representation of the deque
    deque(['f', 'g', 'h', 'i', 'j'])
    >>> d.pop()                 # return and remove the rightmost item
    'j'
    >>> d.popleft()             # return and remove the leftmost item
    'f'
    >>> list(d)                 # list the contents of the deque
    ['g', 'h', 'i']
    >>> 'h' in d                # search the deque
    True
    

    Flera moduler, t.ex. modulerna Queue och threading, utnyttjar nu collections.deque för förbättrad prestanda. (Bidrag från Raymond Hettinger.)

  • Klasserna ConfigParser har förbättrats något. Metoden read() returnerar nu en lista över de filer som har analyserats framgångsrikt, och metoden set() ger upphov till TypeError om ett value-argument som inte är en sträng skickas. (Bidrag från John Belmonte och David Goodger.)

  • Modulen curses har nu stöd för ncurses-tillägget use_default_colors(). På plattformar där terminalen stöder transparens gör detta det möjligt att använda en transparent bakgrund. (Bidrag från Jörg Lehmann.)

  • Modulen difflib innehåller nu en klass HtmlDiff som skapar en HTML-tabell som visar en jämförelse sida vid sida mellan två versioner av en text. (Bidrag från Dan Gass.)

  • Paketet email har uppdaterats till version 3.0, som innehåller flera föråldrade API:er och tar bort stöd för Python-versioner tidigare än 2.3. I version 3.0 av paketet används en ny inkrementell parser för MIME-meddelanden, som finns i modulen email.FeedParser. Den nya parsern kräver inte att hela meddelandet läses in i minnet och ger inte upphov till undantag om ett meddelande är felaktigt utformat; i stället registreras eventuella problem i meddelandets attribut defect. (Utvecklad av Anthony Baxter, Barry Warsaw, Thomas Wouters och andra)

  • Modulen heapq har konverterats till C. Den tiofaldigt förbättrade hastigheten gör att modulen lämpar sig för hantering av stora datamängder. Dessutom har modulen två nya funktioner nlargest() och nsmallest() som använder heaps för att hitta de N största eller minsta värdena i en datauppsättning utan att behöva göra en fullständig sortering. (Bidrag från Raymond Hettinger.)

  • Modulen httplib innehåller nu konstanter för HTTP-statuskoder som definieras i olika HTTP-relaterade RFC-dokument. Konstanterna har namn som OK, CREATED, CONTINUE och MOVED_PERMANENTLY; använd pydoc för att få en fullständig lista. (Bidrag från Andrew Eland.)

  • Modulen imaplib har nu stöd för IMAP:s THREAD-kommando (bidrag från Yves Dionne) och de nya metoderna deleteacl() och myrights() (bidrag från Arnaud Mazin).

  • Modulen itertools har utökats med funktionen groupby(iterable[, *func*]). iterable är något som kan itereras över för att returnera en ström av element, och den valfria parametern func är en funktion som tar ett element och returnerar ett nyckelvärde; om den utelämnas är nyckeln helt enkelt själva elementet. groupby() grupperar sedan elementen i undersekvenser som har matchande värden på nyckeln, och returnerar en serie av 2-tupler som innehåller nyckelvärdet och en iterator över undersekvensen.

    Här är ett exempel för att göra det tydligare. Funktionen key returnerar helt enkelt om ett tal är jämnt eller udda, så resultatet av groupby() är att returnera på varandra följande serier av udda eller jämna tal.

    >>> import itertools
    >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]
    >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):
    ...    print key_val, list(it)
    ...
    0 [2, 4, 6]
    1 [7]
    0 [8]
    1 [9, 11]
    0 [12, 14]
    >>>
    

    groupby() används vanligen med sorterad indata. Logiken för groupby() liknar Unix uniq-filter, vilket gör det praktiskt för att eliminera, räkna eller identifiera duplicerade element:

    >>> word = 'abracadabra'
    >>> letters = sorted(word)   # Turn string into a sorted list of letters
    >>> letters
    ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']
    >>> for k, g in itertools.groupby(letters):
    ...    print k, list(g)
    ...
    a ['a', 'a', 'a', 'a', 'a']
    b ['b', 'b']
    c ['c']
    d ['d']
    r ['r', 'r']
    >>> # List unique letters
    >>> [k for k, g in groupby(letters)]
    ['a', 'b', 'c', 'd', 'r']
    >>> # Count letter occurrences
    >>> [(k, len(list(g))) for k, g in groupby(letters)]
    [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
    

    (Bidrag från Hye-Shik Chang.)

  • itertools har också fått en funktion som heter tee(iterator, N) som returnerar N oberoende iteratorer som replikerar iterator. Om N utelämnas är standardvärdet 2.

    >>> L = [1,2,3]
    >>> i1, i2 = itertools.tee(L)
    >>> i1,i2
    (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)
    >>> list(i1)               # Run the first iterator to exhaustion
    [1, 2, 3]
    >>> list(i2)               # Run the second iterator to exhaustion
    [1, 2, 3]
    

    Observera att tee() måste behålla kopior av de värden som iteratorn returnerar; i värsta fall kan den behöva behålla dem alla. Detta bör därför användas försiktigt om den ledande iteratorn kan springa långt före den efterföljande iteratorn i en lång ström av inmatningar. Om separationen är stor kan du lika gärna använda list() istället. När iteratorerna ligger nära varandra är tee() perfekt. Möjliga tillämpningar inkluderar bokmärken, fönster eller lookahead-iteratorer. (Bidrag från Raymond Hettinger.)

  • Ett antal funktioner har lagts till i modulen locale, t.ex. bind_textdomain_codeset() för att ange en viss kodning och en familj av l*gettext()-funktioner som returnerar meddelanden i den valda kodningen. (Bidrag från Gustavo Niemeyer.)

  • Några nyckelordsargument har lagts till i logging-paketets basicConfig()-funktion för att förenkla loggkonfigurationen. Standardbeteendet är att logga meddelanden till standardfel, men olika nyckelordsargument kan anges för att logga till en viss fil, ändra loggningsformatet eller ställa in loggningsnivån. Till exempel:

    import logging
    logging.basicConfig(filename='/var/log/application.log',
        level=0,  # Log all messages
        format='%(levelname):%(process):%(thread):%(message)')
    

    Andra tillägg till logging-paketet inkluderar en log(level, msg) bekvämlighetsmetod, samt en TimedRotatingFileHandler-klass som roterar sina loggfiler med ett tidsbestämt intervall. Modulen hade redan RotatingFileHandler, som roterade loggarna när filen översteg en viss storlek. Båda klasserna härstammar från en ny klass BaseRotatingHandler som kan användas för att implementera andra rotationshanterare.

    (Ändringar implementerade av Vinay Sajip.)

  • Modulen marshal delar nu internerade strängar vid uppackning av en datastruktur. Detta kan krympa storleken på vissa pickle-strängar, men den primära effekten är att göra .pyc-filer betydligt mindre. (Bidrag från Martin von Löwis.)

  • nntplib-modulens NNTP-klass fick metoderna description() och descriptions() för att hämta beskrivningar av nyhetsgrupper för en enda grupp eller för ett antal grupper. (Bidrag från Jürgen A. Erhard.)

  • Två nya funktioner har lagts till i modulen operator, attrgetter(attr) och itemgetter(index). Båda funktionerna returnerar anropbara filer som tar ett enda argument och returnerar motsvarande attribut eller objekt; dessa anropbara filer är utmärkta datautdragare när de används med map() eller sorted(). Till exempel:

    >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
    >>> map(operator.itemgetter(0), L)
    ['c', 'd', 'a', 'b']
    >>> map(operator.itemgetter(1), L)
    [2, 1, 4, 3]
    >>> sorted(L, key=operator.itemgetter(1)) # Sort list by second tuple item
    [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
    

    (Bidrag från Raymond Hettinger.)

  • Modulen optparse har uppdaterats på olika sätt. Modulen skickar nu sina meddelanden genom gettext.gettext(), vilket gör det möjligt att internationalisera Optiks hjälp- och felmeddelanden. Hjälpmeddelanden för alternativ kan nu inkludera strängen '%default', som kommer att ersättas av alternativets standardvärde. (Bidrag från Greg Ward.)

  • Den långsiktiga planen är att avskaffa rfc822-modulen i någon framtida Python-utgåva till förmån för email-paketet. För detta ändamål har funktionen email.Utils.formatdate ändrats för att göra den användbar som en ersättning för rfc822.formatdate(). Du kanske vill skriva ny kod för e-postbehandling med detta i åtanke. (Ändringen implementerades av Anthony Baxter.)

  • En ny funktion urandom(n) har lagts till i modulen os, som returnerar en sträng innehållande n bytes slumpmässiga data. Denna funktion ger tillgång till plattformsspecifika källor till slumpmässiga data såsom /dev/urandom på Linux eller Windows CryptoAPI. (Bidrag från Trevor Perrin.)

  • Ytterligare en ny funktion: os.path.lexists(path) returnerar sant om filen som anges av path existerar, oavsett om det är en symbolisk länk eller inte. Detta skiljer sig från den befintliga funktionen os.path.exists(path), som returnerar false om path är en symbolisk länk som pekar på en destination som inte existerar. (Bidrag från Beni Cherniavsky.)

  • En ny funktion getsid() lades till i modulen posix som ligger till grund för modulen os. (Bidrag från J. Raynor.)

  • Modulen poplib har nu stöd för POP över SSL. (Bidrag från Hector Urtubia.)

  • Modulen profile kan nu profilera C-tilläggsfunktioner. (Bidrag från Nick Bastin.)

  • Modulen random har en ny metod som heter getrandbits(N) som returnerar ett långt heltal N bitar långt. Den befintliga metoden randrange() använder nu getrandbits() där det är lämpligt, vilket gör generering av godtyckligt stora slumptal mer effektiv. (Bidrag från Raymond Hettinger.)

  • Det språk för reguljära uttryck som accepteras av modulen re har utökats med enkla villkorliga uttryck, skrivna som (?(group)A|B). group är antingen ett numeriskt grupp-ID eller ett gruppnamn definierat med (?P<group>...) tidigare i uttrycket. Om den angivna gruppen matchade, kommer det reguljära uttrycksmönstret A att testas mot strängen; om gruppen inte matchade, kommer mönstret B att användas istället. (Bidrag från Gustavo Niemeyer.)

  • Modulen re är inte heller längre rekursiv, tack vare ett enormt arbete av Gustavo Niemeyer. I en rekursiv reguljär uttrycksmotor resulterar vissa mönster i att en stor mängd C-stackutrymme förbrukas, och det var möjligt att överfylla stacken. Om du till exempel matchade en 30000-byte-sträng med a-tecken mot uttrycket (a|b)+, förbrukades en stackram per tecken. Python 2.3 försökte kontrollera för stacköverflöd och skapa ett RuntimeError-undantag, men vissa mönster kunde kringgå kontrollen och om du hade otur kunde Python få segfault. Python 2.4:s motor för reguljära uttryck kan matcha det här mönstret utan problem.

  • Modulen signal utför nu en striktare felkontroll på parametrarna till funktionen signal.signal(). Till exempel kan du inte ställa in en hanterare på SIGKILL-signalen; tidigare versioner av Python skulle tyst acceptera detta, men 2.4 kommer att ge upphov till ett RuntimeError-undantag.

  • Två nya funktioner har lagts till i modulen socket. socketpair() returnerar ett par anslutna socklar och getservbyport(port) söker upp servicenamnet för ett givet portnummer. (Bidrag från Dave Cole och Barry Warsaw.)

  • Funktionen sys.exitfunc() har utgått. Kod bör använda den befintliga modulen atexit, som korrekt hanterar anrop av flera exit-funktioner. Så småningom kommer sys.exitfunc() att bli ett rent internt gränssnitt, som endast nås av atexit.

  • Modulen tarfile genererar nu tar-filer i GNU-format som standard. (Bidrag från Lars Gustäbel.)

  • Modulen threading har nu ett elegant och enkelt sätt att stödja trådlokala data. Modulen innehåller en local-klass vars attributvärden är lokala för olika trådar.

    import threading
    
    data = threading.local()
    data.number = 42
    data.url = ('www.python.org', 80)
    

    Andra trådar kan tilldela och hämta sina egna värden för attributen number och url. Du kan underklassa local för att initiera attribut eller lägga till metoder. (Bidrag från Jim Fulton.)

  • Modulen timeit inaktiverar nu automatiskt periodisk skräpinsamling under tidtagningsslingan. Denna förändring gör på varandra följande tidtagningar mer jämförbara. (Bidrag från Raymond Hettinger.)

  • Modulen weakref stöder nu ett större antal objekt, inklusive Python-funktioner, klassinstanser, set, frozensets, deques, arrays, filer, sockets och objekt med mönster för reguljära uttryck. (Bidrag från Raymond Hettinger.)

  • Modulen xmlrpclib stöder nu ett tillägg för flera anrop för att överföra flera XML-RPC-anrop i en enda HTTP-operation. (Bidrag från Brian Quinlan.)

  • Modulerna mpz, rotor och xreadlines har tagits bort.

cookielib

Biblioteket cookielib har stöd för hantering av HTTP-cookies på klientsidan och speglar modulen Cookie:s stöd för cookies på serversidan. Cookies lagras i cookie-burkar; biblioteket lagrar på ett transparent sätt cookies som erbjuds av webbservern i cookie-burken och hämtar cookien från burken när du ansluter till servern. Precis som i webbläsare styr policyobjekt om cookies ska accepteras eller inte.

För att kunna lagra cookies över sessioner finns det två implementeringar av cookie jars: en som lagrar cookies i Netscape-format så att program kan använda Mozilla- eller Lynx-cookiefiler, och en som lagrar cookies i samma format som Perl-biblioteket libwww.

urllib2 har ändrats för att interagera med cookielib: HTTPCookieProcessor hanterar en cookiejar som används vid åtkomst till URL:er.

Denna modul har tillhandahållits av John J. Lee.

doctest

Modulen doctest har genomgått en betydande omarbetning tack vare Edward Loper och Tim Peters. Testning kan fortfarande vara lika enkelt som att köra doctest.testmod(), men omarbetningarna gör det möjligt att anpassa modulens funktion på olika sätt

Den nya DocTestFinder-klassen extraherar testerna från ett visst objekts docstrings:

def f (x, y):
    """>>> f(2,2)
4
>>> f(3,2)
6
    """
    return x*y

finder = doctest.DocTestFinder()

# Get list of DocTest instances
tests = finder.find(f)

Den nya DocTestRunner-klassen kör sedan enskilda tester och kan producera en sammanfattning av resultaten:

runner = doctest.DocTestRunner()
för t i tester:
    tried, failed = runner.run(t)

runner.summarize(verbose=1)

Exemplet ovan ger följande resultat:

1 objekt klarade alla tester:
   2 tester i f
2 tester i 1 objekt.
2 godkända och 0 underkända.
Testet godkändes.

DocTestRunner använder en instans av klassen OutputChecker för att jämföra den förväntade utdata med den faktiska utdata. Denna klass tar ett antal olika flaggor som anpassar dess beteende; ambitiösa användare kan också skriva en helt ny underklass av OutputChecker.

Standardutdatakontrollen har ett antal praktiska funktioner. Till exempel, med doctest.ELLIPSIS option flagga, en ellips (...) i den förväntade utdata matchar alla delsträngar, vilket gör det lättare att tillgodose utdata som varierar på mindre sätt:

def o (n):
    """>>> o(1)
<__main__.C instance at 0x...>
>>>
"""

En annan speciell sträng, <BLANKLINE>, matchar en tom rad:

def p (n):
    """>>> p(1)
<BLANKLINE>
>>>
"""

En annan ny funktion är att producera en diff-stilsvisning av utdata genom att ange alternativflaggorna doctest.REPORT_UDIFF (unified diffs), doctest.REPORT_CDIFF (context diffs) eller doctest.REPORT_NDIFF (delta-style). Till exempel:

def g (n):
    """>>> g(4)
here
is
a
lengthy
>>>"""
    L = 'here is a rather lengthy list of words'.split()
    for word in L[:n]:
        print word

Om du kör testerna för ovanstående funktion med doctest.REPORT_UDIFF specificerad får du följande resultat:

**********************************************************************
Fil "t.py", rad 15, i g
Misslyckat exempel:
    g(4)
Skillnader (enhetlig diff med -förväntat +verkligt):
    @@ -2,3 +2,3 @@
     är
     a
    -lång
    +mer
**********************************************************************

Ändringar i Build och C API

Några av ändringarna i Pythons byggprocess och i C API:et är följande:

  • Tre nya bekvämlighetsmakron har lagts till för vanliga returvärden från tilläggsfunktioner: Py_RETURN_NONE, Py_RETURN_TRUE och Py_RETURN_FALSE. (Bidrag från Brett Cannon.)

  • Ett annat nytt makro, Py_CLEAR, minskar referensantalet för obj och sätter obj till nollpekaren. (Bidrag från Jim Fulton.)

  • En ny funktion, PyTuple_Pack(N, obj1, obj2, ..., objN), konstruerar tuplar från en argumentlista med variabel längd av Python-objekt. (Bidrag från Raymond Hettinger.)

  • En ny funktion, PyDict_Contains(d, k), implementerar snabba ordboksuppslagningar utan att maskera undantag som uppstår under uppslagningsprocessen. (Bidrag från Raymond Hettinger.)

  • Makrot Py_IS_NAN(X) returnerar 1 om dess float- eller double-argument X är ett NaN. (Bidrag från Tim Peters.)

  • C-kod kan undvika onödig låsning genom att använda den nya PyEval_ThreadsInitialized()-funktionen för att avgöra om några trådoperationer har utförts. Om denna funktion returnerar false behövs inga låsoperationer. (Bidrag från Nick Coghlan.)

  • En ny funktion, PyArg_VaParseTupleAndKeywords(), är samma sak som PyArg_ParseTupleAndKeywords() men tar en va_list istället för ett antal argument. (Bidrag från Greg Chapman.)

  • En ny metodflagga, METH_COEXIST, gör att en funktion som definieras i slots kan samexistera med en PyCFunction med samma namn. Detta kan halvera åtkomsttiden för en metod som set.__contains__(). (Bidrag från Raymond Hettinger.)

  • Python kan nu byggas med ytterligare profilering för själva tolken, avsedd som ett hjälpmedel för personer som utvecklar Python-kärnan. Om du lägger till --enable-profiling i skriptet configure kan du profilera tolken med gprof, och om du lägger till --with-tsc kan du profilera med hjälp av Pentiums Time-Stamp-Counter-register. Observera att bytet --with-tsc är något felaktigt namngivet, eftersom profileringsfunktionen även fungerar på PowerPC-plattformen, även om den processorarkitekturen inte kallar registret för ”TSC-registret”. (Bidrag från Jeremy Hylton.)

  • Typen tracebackobject har bytt namn till PyTracebackObject.

Hamnspecifika ändringar

  • Windows-porten bygger nu under MSVC++ 7.1 såväl som version 6. (Bidrag från Martin von Löwis.)

Portning till Python 2.4

I detta avsnitt listas tidigare beskrivna ändringar som kan kräva ändringar i din kod:

  • Vänsterförskjutningar och hexadecimala/oktala konstanter som är för stora utlöser inte längre en FutureWarning och returnerar ett värde begränsat till 32 eller 64 bitar; istället returnerar de ett långt heltal.

  • Integer-operationer kommer inte längre att utlösa en OverflowWarning. Varningen OverflowWarning kommer att försvinna i Python 2.5.

  • De inbyggda funktionerna zip() och itertools.izip() returnerar nu en tom lista istället för att ge upphov till ett TypeError-undantag om de anropas utan argument.

  • Du kan inte längre jämföra instanserna date och datetime som tillhandahålls av modulen datetime. Två instanser av olika klasser kommer nu alltid att vara ojämlika och relativa jämförelser (<, >) kommer att ge upphov till ett TypeError.

  • dircache.listdir() skickar nu undantag till anroparen istället för att returnera tomma listor.

  • LexicalHandler.startDTD() brukade ta emot offentliga ID:n och system-ID:n i fel ordning. Detta har korrigerats; applikationer som förlitar sig på den felaktiga ordningen måste åtgärdas.

  • fcntl.ioctl() varnar nu om argumentet mutate utelämnas och är relevant.

  • Modulen tarfile genererar nu tar-filer i GNU-format som standard.

  • Om ett fel inträffar vid import av en modul lämnas inte längre ett delvis initialiserat modulobjekt kvar i sys.modules.

  • None är nu en konstant; kod som binder ett nytt värde till namnet None är nu ett syntaxfel.

  • Funktionen signals.signal() ger nu upphov till ett RuntimeError-undantag för vissa olagliga värden; tidigare passerade dessa fel tyst. Du kan t.ex. inte längre ställa in en hanterare för signalen SIGKILL.

Tack till

Författaren vill tacka följande personer för förslag, korrigeringar och hjälp med olika utkast av denna artikel: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.