Vad är nytt i Python 2.2¶
- Författare:
A.M. Kuchling
Introduktion¶
Den här artikeln förklarar de nya funktionerna i Python 2.2.2, som släpptes den 14 oktober 2002. Python 2.2.2 är en buggfixversion av Python 2.2, som ursprungligen släpptes den 21 december 2001.
Python 2.2 kan betraktas som en ”uppstädningsversion”. Det finns några funktioner som generatorer och iteratorer som är helt nya, men de flesta av ändringarna, även om de är betydande och långtgående, syftar till att rensa upp oegentligheter och mörka hörn i språkdesignen.
Den här artikeln är inte ett försök att ge en fullständig specifikation av de nya funktionerna, utan ger istället en praktisk översikt. För fullständiga detaljer bör du läsa dokumentationen för Python 2.2, till exempel Python Library Reference och Python Reference Manual. Om du vill förstå den fullständiga implementeringen och designrationalen för en ändring, se PEP för en viss ny funktion.
PEP 252 och 253: Ändringar av typ och klass¶
De största och mest långtgående förändringarna i Python 2.2 gäller Pythons modell för objekt och klasser. Ändringarna bör vara bakåtkompatibla, så det är troligt att din kod kommer att fortsätta att köras oförändrad, men ändringarna ger några fantastiska nya funktioner. Innan jag börjar med detta, det längsta och mest komplicerade avsnittet i den här artikeln, ska jag ge en översikt över ändringarna och ge några kommentarer.
För länge sedan skrev jag en webbsida som listade brister i Pythons design. En av de mest betydande bristerna var att det är omöjligt att subklassa Python-typer som implementerats i C. I synnerhet är det inte möjligt att subklassa inbyggda typer, så du kan inte bara subklassa, säg, listor för att lägga till en enda användbar metod till dem. Modulen UserList
tillhandahåller en klass som stöder alla metoder för listor och som kan subklassas ytterligare, men det finns massor av C-kod som förväntar sig en vanlig Python-lista och inte accepterar en UserList
-instans.
Python 2.2 åtgärdar detta och lägger samtidigt till några spännande nya funktioner. En kort sammanfattning:
Du kan subklassa inbyggda typer som listor och till och med heltal, och dina subklasser ska fungera på alla ställen som kräver den ursprungliga typen.
Det är nu möjligt att definiera statiska metoder och klassmetoder, utöver de instansmetoder som fanns i tidigare versioner av Python.
Det är också möjligt att automatiskt anropa metoder för att komma åt eller ställa in ett instansattribut genom att använda en ny mekanism som kallas properties. Många användningar av
__getattr__()
kan skrivas om för att använda egenskaper istället, vilket gör den resulterande koden enklare och snabbare. Som en liten sidofördel kan attribut nu också ha docstrings.Listan över lagliga attribut för en instans kan begränsas till en viss uppsättning med hjälp av slots, vilket gör det möjligt att skydda sig mot typfel och kanske göra fler optimeringar möjliga i framtida versioner av Python.
Vissa användare har uttryckt oro över alla dessa förändringar. Visst, säger de, de nya funktionerna är snygga och lämpar sig för alla möjliga knep som inte var möjliga i tidigare versioner av Python, men de gör också språket mer komplicerat. Vissa människor har sagt att de alltid har rekommenderat Python för dess enkelhet och känner att dess enkelhet går förlorad.
Personligen tycker jag inte att det finns någon anledning att oroa sig. Många av de nya funktionerna är ganska esoteriska, och du kan skriva mycket Python-kod utan att någonsin behöva vara medveten om dem. Att skriva en enkel klass är inte svårare än det någonsin varit, så du behöver inte bry dig om att lära dig eller lära ut dem om de inte faktiskt behövs. Vissa mycket komplicerade uppgifter som tidigare bara var möjliga från C kommer nu att vara möjliga i ren Python, och enligt min mening är det allt till det bättre.
Jag tänker inte försöka gå igenom varje enskilt hörnfall och liten förändring som krävdes för att få de nya funktionerna att fungera. Istället kommer det här avsnittet bara att måla de breda penseldragen. Se avsnitt Relaterade länkar, ”Relaterade länkar”, för ytterligare informationskällor om Python 2.2:s nya objektmodell.
Gamla och nya klasser¶
Först bör du veta att Python 2.2 verkligen har två typer av klasser: klassiska eller gamla klasser och nya klasser. Klassmodellen i den gamla stilen är exakt densamma som klassmodellen i tidigare versioner av Python. Alla nya funktioner som beskrivs i det här avsnittet gäller bara för klasser av ny typ. Denna skillnad är inte avsedd att vara för evigt; så småningom kommer klasser i gammal stil att tas bort, möjligen i Python 3.0.
Så hur definierar man en new-style class? Det gör man genom att subklassa en befintlig new-style class. De flesta av Pythons inbyggda typer, som heltal, listor, ordböcker och till och med filer, är nu new-style-klasser. En ny stilklass med namnet object
, basklassen för alla inbyggda typer, har också lagts till så om ingen inbyggd typ är lämplig kan du bara subklassa object
:
class C(object):
def __init__ (self):
...
...
Detta innebär att class
-satser som inte har några basklasser alltid är klassiska klasser i Python 2.2. (Egentligen kan du också ändra detta genom att ställa in en variabel på modulnivå som heter __metaclass__
— se PEP 253 för detaljerna — men det är lättare att bara subklassa object
.)
Typobjekten för de inbyggda typerna finns tillgängliga som inbyggda funktioner, namngivna med hjälp av ett smart trick. Python har alltid haft inbyggda funktioner med namnen int()
, float()
och str()
. I 2.2 är de inte längre funktioner, utan typobjekt som beter sig som fabriker när de anropas.
>>> int
<type 'int'>
>>> int('123')
123
För att göra uppsättningen av typer komplett har nya typobjekt som dict()
och file()
lagts till. Här är ett mer intressant exempel, där vi lägger till en lock()
-metod till filobjekt:
class LockableFile(file):
def lock (self, operation, length=0, start=0, whence=0):
import fcntl
return fcntl.lockf(self.fileno(), operation,
length, start, whence)
Den numera obsoleta modulen posixfile
innehöll en klass som emulerade alla ett filobjekts metoder och lade även till en lock()
-metod, men den här klassen kunde inte skickas till interna funktioner som förväntade sig en inbyggd fil, något som är möjligt med vår nya LockableFile
.
Deskriptorer¶
I tidigare versioner av Python fanns det inget konsekvent sätt att upptäcka vilka attribut och metoder som stöddes av ett objekt. Det fanns några informella konventioner, som att definiera attributen __members__
och __methods__
som var namnlistor, men ofta brydde sig inte författaren till en extensionstyp eller en klass om att definiera dem. Man kunde falla tillbaka på att inspektera __dict__
för ett objekt, men när klassarv eller en godtycklig __getattr__()
-hook användes kunde detta fortfarande vara felaktigt.
Den stora idén bakom den nya klassmodellen är att ett API för att beskriva attributen hos ett objekt med hjälp av descriptors har formaliserats. Descriptors specificerar värdet på ett attribut och anger om det är en metod eller ett fält. Med API:et för deskriptorer blir statiska metoder och klassmetoder möjliga, liksom mer exotiska konstruktioner.
Attributbeskrivare är objekt som finns inuti klassobjekt och som har några egna attribut:
__name__
är attributets namn.__doc__
är attributets docstring.__get__(object)
är en metod som hämtar attributvärdet från object.__set__(object, value)
sätter attributet på objekt till värde.__delete__(object, value)
raderar attributet value i object.
När du till exempel skriver obj.x
är de steg som Python faktiskt utför följande:
descriptor = obj.__class__.x
descriptor.__get__(obj)
För metoder returnerar descriptor.__get__
ett temporärt objekt som kan anropas och som innehåller instansen och den metod som ska anropas på den. Det är också därför som statiska metoder och klassmetoder nu är möjliga; de har deskriptorer som omsluter bara metoden, eller metoden och klassen. En kort förklaring av dessa nya typer av metoder är att statiska metoder inte får instansen och därför liknar vanliga funktioner. Klassmetoder får objektets klass, men inte själva objektet. Statiska metoder och klassmetoder definieras så här:
class C(object):
def f(arg1, arg2):
...
f = staticmethod(f)
def g(cls, arg1, arg2):
...
g = classmethod(g)
Funktionen staticmethod()
tar funktionen f()
och returnerar den inslagen i en deskriptor så att den kan lagras i klassobjektet. Du kanske förväntar dig att det ska finnas en speciell syntax för att skapa sådana metoder (def static f
, defstatic f()
, eller något liknande) men ingen sådan syntax har definierats ännu; det har lämnats till framtida versioner av Python.
Fler nya funktioner, som slots och properties, implementeras också som nya typer av descriptors, och det är inte svårt att skriva en descriptor-klass som gör något nytt. Det skulle till exempel vara möjligt att skriva en deskriptorklass som gör det möjligt att skriva för- och eftervillkor i Eiffelstil för en metod. En klass som använder denna funktion skulle kunna definieras så här:
from eiffel import eiffelmethod
class C(object):
def f(self, arg1, arg2):
# The actual function
...
def pre_f(self):
# Check preconditions
...
def post_f(self):
# Check postconditions
...
f = eiffelmethod(f, pre_f, post_f)
Observera att en person som använder den nya eiffelmethod()
inte behöver förstå någonting om deskriptorer. Det är därför jag tror att de nya funktionerna inte ökar språkets grundläggande komplexitet. Det kommer att finnas några trollkarlar som behöver känna till det för att kunna skriva eiffelmethod()
eller ZODB eller vad som helst, men de flesta användare kommer bara att skriva kod ovanpå de resulterande biblioteken och ignorera implementationsdetaljerna.
Multipel arvbarhet: Diamantregeln¶
Multipel nedärvning har också gjorts mer användbar genom att ändra reglerna för hur namn löses. Tänk på denna uppsättning klasser (diagrammet är hämtat från PEP 253 av Guido van Rossum):
class A:
^ ^ def save(self): ...
/ \
/ \
/ \
/ \
class B class C:
^ ^ def save(self): ...
\ /
\ /
\ /
\ /
class D
Uppslagsregeln för klassiska klasser är enkel men inte särskilt smart; basklasserna söks djupt först, från vänster till höger. En referens till D.save()
kommer att söka i klasserna D
, B
, och sedan A
, där save()
skulle hittas och returneras. C.save()
skulle aldrig hittas alls. Det här är dåligt, för om C
:s save()
-metod sparar något internt tillstånd som är specifikt för C
, kommer det att resultera i att tillståndet aldrig sparas om den inte anropas.
New-style klasser följer en annan algoritm som är lite mer komplicerad att förklara, men som gör rätt sak i den här situationen. (Observera att Python 2.3 ändrar denna algoritm till en som ger samma resultat i de flesta fall, men som ger mer användbara resultat för riktigt komplicerade arvsgrafer)
Lista alla basklasser, enligt den klassiska lookup-regeln och inkludera en klass flera gånger om den besöks upprepade gånger. I exemplet ovan är listan över besökta klasser [
D
,B
,A
,C
,A
].Sök igenom listan efter dubblerade klasser. Om några hittas, ta bort alla utom en förekomst och lämna den sista i listan. I exemplet ovan blir listan [
D
,B
,C
,A
] efter att dubbletter har tagits bort.
Enligt denna regel kommer en hänvisning till D.save()
att returnera C.save()
, vilket är det beteende vi är ute efter. Denna uppslagsregel är densamma som den som Common Lisp följer. En ny inbyggd funktion, super()
, ger ett sätt att komma åt en klass superklasser utan att behöva omimplementera Pythons algoritm. Den vanligaste formen kommer att vara super(class, obj)
, som returnerar ett bundet superklassobjekt (inte det faktiska klassobjektet). Denna form kommer att användas i metoder för att anropa en metod i superklassen; till exempel skulle D
:s save()
-metod se ut så här:
class D (B,C):
def save (self):
# Call superclass .save()
super(D, self).save()
# Save D's private information here
...
super()
kan också returnera obundna superklassobjekt när den anropas som super(class)
eller super(class1, class2)
, men detta kommer förmodligen inte ofta att vara användbart.
Attributåtkomst¶
Ett stort antal sofistikerade Python-klasser definierar hooks för attributåtkomst med __getattr__()
; oftast görs detta för enkelhetens skull, för att göra koden mer läsbar genom att automatiskt mappa en attributåtkomst som obj.parent
till ett metodanrop som obj.get_parent
. Python 2.2 lägger till några nya sätt att kontrollera attributåtkomst.
För det första stöds __getattr__(attr_name)
fortfarande av new-style klasser, och ingenting har ändrats. Precis som tidigare kommer den att anropas när ett försök görs att komma åt obj.foo
och inget attribut med namnet foo
hittas i instansens dictionary.
New-style klasser har också stöd för en ny metod, __getattribute__(attr_name)
. Skillnaden mellan de två metoderna är att __getattribute__()
alltid anropas när något attribut används, medan den gamla __getattr__()
bara anropas om foo
inte finns i instansens dictionary.
Python 2.2:s stöd för properties kommer dock ofta att vara ett enklare sätt att fånga attributreferenser. Att skriva en __getattr__()
-metod är komplicerat eftersom man för att undvika rekursion inte kan använda vanliga attributåtkomster inuti dem, utan istället måste röra runt med innehållet i __dict__
. metoderna __getattr__()
anropas också av Python när den söker efter andra metoder som __repr__()
eller __coerce__()
, och måste därför skrivas med detta i åtanke. Slutligen leder anrop av en funktion vid varje attributåtkomst till en avsevärd prestandaförlust.
property
är en ny inbyggd typ som innehåller tre funktioner som hämtar, ställer in eller tar bort ett attribut samt en dokumentsträng. Om du till exempel vill definiera ett size
-attribut som är beräknat, men också inställbart, kan du skriva:
class C(object):
def get_size (self):
result = ... computation ...
return result
def set_size (self, size):
... compute something based on the size
and set internal state appropriately ...
# Define a property. The 'delete this attribute'
# method is defined as None, so the attribute
# can't be deleted.
size = property(get_size, set_size,
None,
"Storage size of this instance")
Det är i alla fall tydligare och enklare att skriva än ett par __getattr__()
/__setattr__()
-metoder som söker efter attributet size
och hanterar det speciellt medan de hämtar alla andra attribut från instansens __dict__
. Åtkomster till size
är också de enda som måste utföra arbetet med att anropa en funktion, så referenser till andra attribut körs med sin vanliga hastighet.
Slutligen är det möjligt att begränsa listan över attribut som kan refereras till på ett objekt med hjälp av det nya klassattributet __slots__
. Python-objekt är vanligtvis mycket dynamiska; när som helst är det möjligt att definiera ett nytt attribut på en instans genom att bara göra obj.new_attr=1
. En klass med ny stil kan definiera ett klassattribut med namnet __slots__
för att begränsa de lagliga attributen till en viss uppsättning namn. Ett exempel kommer att göra detta tydligt:
>>> class C(object):
... __slots__ = ('template', 'name')
...
>>> obj = C()
>>> print obj.template
None
>>> obj.template = 'Test'
>>> print obj.template
Test
>>> obj.newattr = None
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'C' object has no attribute 'newattr'
Observera att du får ett AttributeError
när du försöker tilldela ett attribut som inte finns med i __slots__
.
PEP 234: Iteratorer¶
Ett annat viktigt tillägg till 2.2 är ett iterationsgränssnitt på både C- och Python-nivå. Objekt kan definiera hur de kan loopas över av anropare.
I Python-versioner upp till 2.1 är det vanliga sättet att få for item in obj
att fungera att definiera en __getitem__()
-metod som ser ut ungefär så här:
def __getitem__(self, index):
return <next item>
__getitem__()
används mer korrekt för att definiera en indexeringsoperation på ett objekt så att du kan skriva obj[5]
för att hämta det sjätte elementet. Det är lite missvisande när du bara använder detta för att stödja for
-loopar. Tänk på något filliknande objekt som vill loopas över; parametern index är i princip meningslös, eftersom klassen förmodligen antar att en serie __getitem__()
-anrop kommer att göras med index som ökar med ett varje gång. Med andra ord betyder inte förekomsten av metoden __getitem__()
att det fungerar att använda file[5]
för att slumpmässigt komma åt det sjätte elementet, även om det verkligen borde göra det.
I Python 2.2 kan iteration implementeras separat och __getitem__()
-metoder kan begränsas till klasser som verkligen stöder slumpmässig åtkomst. Grundidén med iteratorer är enkel. En ny inbyggd funktion, iter(obj)
eller iter(C, sentinel)
, används för att hämta en iterator. iter(obj)
returnerar en iterator för objektet obj, medan iter(C, sentinel)
returnerar en iterator som kommer att anropa det anropbara objektet C tills det returnerar sentinel för att signalera att iteratorn är klar.
Python-klasser kan definiera en __iter__()
-metod, som ska skapa och returnera en ny iterator för objektet; om objektet är sin egen iterator kan denna metod bara returnera self
. I synnerhet iteratorer kommer vanligtvis att vara sina egna iteratorer. Tilläggstyper implementerade i C kan implementera en tp_iter
-funktion för att returnera en iterator, och tilläggstyper som vill bete sig som iteratorer kan definiera en tp_iternext
-funktion.
Så, efter allt detta, vad gör iteratorer egentligen? De har en obligatorisk metod, next()
, som inte tar några argument och returnerar nästa värde. När det inte finns fler värden att returnera bör anrop av next()
ge upphov till undantaget StopIteration
.
>>> L = [1,2,3]
>>> i = iter(L)
>>> print i
<iterator object at 0x8116870>
>>> i.next()
1
>>> i.next()
2
>>> i.next()
3
>>> i.next()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
>>>
I 2.2 förväntar sig Pythons for
-sats inte längre en sekvens; den förväntar sig något som iter()
returnerar en iterator för. För bakåtkompatibilitet och bekvämlighet konstrueras en iterator automatiskt för sekvenser som inte implementerar __iter__()
eller en tp_iter
slot, så for i in [1,2,3]
kommer fortfarande att fungera. Varhelst Python-tolken loopar över en sekvens har den ändrats för att använda iteratorprotokollet. Detta innebär att du kan göra saker som detta:
>>> L = [1,2,3]
>>> i = iter(L)
>>> a,b,c = i
>>> a,b,c
(1, 2, 3)
Iteratorstöd har lagts till i några av Pythons grundläggande typer. Om man anropar iter()
på en ordbok returneras en iterator som loopar över dess nycklar:
>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
... 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m: print key, m[key]
...
Mar 3
Feb 2
Aug 8
Sep 9
May 5
Jun 6
Jul 7
Jan 1
Apr 4
Nov 11
Dec 12
Oct 10
Det är bara standardbeteendet. Om du vill iterera över nycklar, värden eller nyckel/värde-par kan du uttryckligen anropa metoderna iterkeys()
, itervalues()
eller iteritems()
för att få en lämplig iterator. I en mindre relaterad ändring fungerar operatorn in
nu på lexikon, så key in dict
är nu ekvivalent med dict.has_key(key)
.
Filer innehåller också en iterator som anropar metoden readline()
tills det inte finns några fler rader i filen. Detta innebär att du nu kan läsa varje rad i en fil med kod som denna:
för rad i filen:
# gör något för varje rad
...
Observera att du bara kan gå framåt i en iterator; det finns inget sätt att hämta föregående element, återställa iteratorn eller göra en kopia av den. Ett iteratorobjekt kan ge sådana ytterligare möjligheter, men iteratorprotokollet kräver bara en next()
-metod.
Se även
- PEP 234 - Iteratorer
Skriven av Ka-Ping Yee och GvR; implementerad av Python Labs, främst av GvR och Tim Peters.
PEP 255: Enkla generatorer¶
Generatorer är en annan ny funktion, som samverkar med införandet av iteratorer.
Du är säkert bekant med hur funktionsanrop fungerar i Python eller C. När du anropar en funktion får den ett privat namnrymd där dess lokala variabler skapas. När funktionen når en return
-sats förstörs de lokala variablerna och det resulterande värdet returneras till anroparen. Ett senare anrop till samma funktion kommer att få en ny uppsättning lokala variabler. Men tänk om de lokala variablerna inte kastades bort när en funktion avslutades? Tänk om du senare kunde återuppta funktionen där den slutade? Detta är vad generatorer tillhandahåller; de kan betraktas som återupptagbara funktioner.
Här är det enklaste exemplet på en generatorfunktion:
def generera_ints(N):
för i i intervall(N):
avkastning i
Ett nytt nyckelord, yield
, introducerades för generatorer. Varje funktion som innehåller en yield
-sats är en generatorfunktion; detta upptäcks av Pythons bytekodskompilator som kompilerar funktionen speciellt som ett resultat. Eftersom ett nytt nyckelord introducerades måste generatorer uttryckligen aktiveras i en modul genom att inkludera ett from __future__ import generators
-sats nära toppen av modulens källkod. I Python 2.3 kommer detta uttalande att bli onödigt.
När du anropar en generatorfunktion returnerar den inte ett enda värde, utan istället ett generatorobjekt som stöder iteratorprotokollet. Vid exekvering av yield
-satsen matar generatorn ut värdet på i
, på samma sätt som en return
-sats. Den stora skillnaden mellan yield
och en return
-sats är att när man når en yield
avbryts generatorns exekveringstillstånd och lokala variabler bevaras. Vid nästa anrop till generatorns next()
-metod kommer funktionen att återuppta exekveringen omedelbart efter yield
-satsen. (Av komplicerade skäl är yield
-satsen inte tillåten inuti try
-blocket i en try
…finally
-sats; läs PEP 255 för en fullständig förklaring av interaktionen mellan yield
och undantag)
Här är ett exempel på användning av generatorn generate_ints()
:
>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in generate_ints
StopIteration
Du kan lika gärna skriva for i in generate_ints(5)
, eller a,b,c = generate_ints(3)
.
I en generatorfunktion kan return
bara användas utan ett värde och signalerar slutet på värdeförloppet; därefter kan generatorn inte returnera några ytterligare värden. return
med ett värde, t.ex. return 5
, är ett syntaxfel i en generatorfunktion. Slutet på generatorns resultat kan också indikeras genom att höja StopIteration
manuellt, eller genom att bara låta flödet av exekveringen falla från botten av funktionen.
Du kan uppnå effekten av generatorer manuellt genom att skriva din egen klass och lagra alla lokala variabler i generatorn som instansvariabler. Att returnera en lista med heltal kan till exempel göras genom att sätta self.count
till 0 och låta next()
-metoden öka self.count
och returnera den. Men för en måttligt komplicerad generator skulle det vara mycket krångligare att skriva en motsvarande klass. Lib/test/test_generators.py
innehåller ett antal mer intressanta exempel. Det enklaste implementerar en genomgång av ett träd i ordningsföljd med hjälp av generatorer rekursivt.
# En rekursiv generator som genererar trädblad i ordning.
def inorder(t):
if t:
för x i inorder(t.left):
avkastning x
yield t.etikett
för x i inorder(t.right):
ge x
Två andra exempel i Lib/test/test_generators.py
producerar lösningar för N-Queens-problemet (placera $N$ drottningar på ett $NxN$ schackbräde så att ingen drottning hotar en annan) och Knight’s Tour (en rutt som tar en springare till varje ruta på ett $NxN$ schackbräde utan att besöka någon ruta två gånger).
Idén med generatorer kommer från andra programmeringsspråk, särskilt Icon (https://www2.cs.arizona.edu/icon/), där idén med generatorer är central. I Icon beter sig varje uttryck och funktionsanrop som en generator. Ett exempel från ”An Overview of the Icon Programming Language” på https://www2.cs.arizona.edu/icon/docs/ipd266.htm ger en uppfattning om hur detta ser ut:
mening := "Förvara den i den närliggande hamnen"
if (i := find("eller", mening)) > 5 då skriv(i)
I Icon returnerar funktionen find()
de index där delsträngen ”or” hittas: 3, 23, 33. I if
-satsen tilldelas i
först värdet 3, men 3 är mindre än 5, så jämförelsen misslyckas, och Icon gör ett nytt försök med det andra värdet 23. 23 är större än 5, så jämförelsen lyckas nu, och koden skriver ut värdet 23 på skärmen.
Python går inte alls lika långt som Icon när det gäller att anta generatorer som ett centralt koncept. Generatorer betraktas som en ny del av Pythons kärnspråk, men det är inte obligatoriskt att lära sig eller använda dem; om de inte löser några problem som du har, kan du gärna ignorera dem. En nyhet i Pythons gränssnitt jämfört med Icons är att en generators tillstånd representeras som ett konkret objekt (iteratorn) som kan skickas runt till andra funktioner eller lagras i en datastruktur.
Se även
- PEP 255 - Enkla generatorer
Skriven av Neil Schemenauer, Tim Peters, Magnus Lie Hetland. Implementerad mestadels av Neil Schemenauer och Tim Peters, med andra korrigeringar från Python Labs-gänget.
PEP 237: Förenande av långa heltal och heltal¶
I de senaste versionerna har skillnaden mellan vanliga heltal, som är 32-bitarsvärden på de flesta maskiner, och långa heltal, som kan vara av godtycklig storlek, blivit ett irritationsmoment. På plattformar som stöder filer som är större än 2**32
bytes måste till exempel tell()
-metoden för filobjekt returnera ett långt heltal. Det fanns dock olika delar av Python som förväntade sig vanliga heltal och skulle ge upphov till ett fel om ett långt heltal tillhandahölls istället. Till exempel i Python 1.5 kunde endast vanliga heltal användas som ett skivindex, och 'abc'[1L:]
skulle ge upphov till ett TypeError
-undantag med meddelandet ”skivindex måste vara int”.
Python 2.2 kommer att skifta värden från korta till långa heltal vid behov. Suffixet ”L” behövs inte längre för att ange en lång heltalslitteral, eftersom kompilatorn nu väljer lämplig typ. (Att använda suffixet ’L’ kommer att avrådas i framtida 2.x versioner av Python, utlösa en varning i Python 2.4 och troligen tas bort i Python 3.0.) Många operationer som tidigare gav upphov till ett OverflowError
kommer nu att returnera ett långt heltal som resultat. Till exempel:
>>> 1234567890123
1234567890123L
>>> 2 ** 64
18446744073709551616L
I de flesta fall kommer heltal och långa heltal nu att behandlas identiskt. Du kan fortfarande skilja dem åt med den inbyggda funktionen type()
, men det behövs sällan.
Se även
- PEP 237 - Unifiera långa heltal och heltal
Skriven av Moshe Zadka och Guido van Rossum. Implementerad mestadels av Guido van Rossum.
PEP 238: Byte av divisionsoperator¶
Den mest kontroversiella förändringen i Python 2.2 är början på ett försök att åtgärda ett gammalt designfel som har funnits i Python från början. För närvarande beter sig Pythons divisionsoperator, /
, som C: s divisionsoperator när den presenteras med två heltalsargument: den returnerar ett heltalsresultat som trunkeras ner när det skulle finnas en bråkdel. Till exempel är 3/2
1, inte 1,5, och (-1)/2
är -1, inte -0,5. Detta innebär att resultatet av division kan variera oväntat beroende på typen av de två operanderna och eftersom Python är dynamiskt typat kan det vara svårt att avgöra de möjliga typerna av operanderna.
(Kontroversen handlar om huruvida detta verkligen är ett designfel och om det är värt att bryta befintlig kod för att åtgärda det. Det har orsakat oändliga diskussioner på python-dev, och i juli 2001 utbröt en storm av syrligt sarkastiska inlägg på comp.lang.python. Jag kommer inte att argumentera för någon av sidorna här utan hålla mig till att beskriva vad som implementerats i 2.2. Läs PEP 238 för en sammanfattning av argument och motargument)
Eftersom den här förändringen kan bryta kod införs den mycket gradvis. Python 2.2 påbörjar övergången, men bytet kommer inte att vara fullständigt förrän Python 3.0.
Först lånar jag lite terminologi från PEP 238. ”Sann division” är den division som de flesta icke-programmerare är bekanta med: 3/2 är 1,5, 1/4 är 0,25 och så vidare. ”Golvdelning” är vad Pythons operator /
gör när den får heltal som operander; resultatet är golvet av värdet som returneras av sann delning. ”Klassisk delning” är det nuvarande blandade beteendet hos /
; den returnerar resultatet av golvdelning när operanderna är heltal och returnerar resultatet av sann delning när en av operanderna är ett flyttal.
Här är de förändringar som 2.2 introducerar:
En ny operator,
//
, är operatorn för våningsdivision. (Ja, vi vet att den ser ut som C++:s kommentarssymbol.)//
utför alltid golvdivision oavsett vilken typ operanden har, så1 // 2
är 0 och1.0 // 2.0
är också 0.0.//
är alltid tillgängligt i Python 2.2; du behöver inte aktivera det med hjälp av ett__future__
-sats.Genom att inkludera
from __future__ import division
i en modul kommer operatorn/
att ändras så att den returnerar resultatet av en sann division, så att1/2
blir 0,5. Utan__future__
-satsen betyder/
fortfarande klassisk division. Standardbetydelsen av/
kommer inte att ändras förrän i Python 3.0.Klasser kan definiera metoder som kallas
__truediv__()
och__floordiv__()
för att överbelasta de två divisionsoperatorerna. På C-nivå finns det också platser i strukturenPyNumberMethods
så att tilläggstyper kan definiera de två operatorerna.Python 2.2 stöder några kommandoradsargument för att testa om koden kommer att fungera med den ändrade divisionssemantiken. Om du kör python med
-Q warn
kommer en varning att utfärdas när division tillämpas på två heltal. Du kan använda detta för att hitta kod som påverkas av ändringen och fixa den. Som standard kommer Python 2.2 helt enkelt att utföra klassisk division utan varning; varningen kommer att aktiveras som standard i Python 2.3.
Se även
- PEP 238 - Byte av divisionsoperator
Skriven av Moshe Zadka och Guido van Rossum. Implementerad av Guido van Rossum…
Unicode-ändringar¶
Pythons Unicode-stöd har förbättrats en del i 2.2. Unicode-strängar lagras vanligtvis som UCS-2, som 16-bitars osignerade heltal. Python 2.2 kan också kompileras för att använda UCS-4, 32-bitars osignerade heltal, som sin interna kodning genom att ange --enable-unicode=ucs4
till configure-skriptet. (Det är också möjligt att ange --disable-unicode
för att helt inaktivera Unicode-stöd)
När tolken är byggd för att använda UCS-4 (ett ”brett Python”) kan den naturligt hantera Unicode-tecken från U+000000 till U+110000, så intervallet av lagliga värden för funktionen unichr()
utökas i enlighet med detta. Om du använder en tolk som är kompilerad för att använda UCS-2 (ett ”smalt Python”), kommer värden större än 65535 fortfarande att orsaka att unichr()
ger upphov till ett ValueError
undantag. Allt detta beskrivs i PEP 261, ”Support for ’wide’ Unicode characters”; se den för ytterligare detaljer.
En annan förändring är enklare att förklara. Unicode-strängar har sedan de introducerades haft stöd för en encode()
-metod för att konvertera strängen till en vald kodning som UTF-8 eller Latin-1. En symmetrisk metod decode([*encoding*])
har lagts till för 8-bitars strängar (dock inte för Unicode-strängar) i 2.2. decode()
antar att strängen är i den angivna kodningen och avkodar den och returnerar vad som returneras av codec.
Med hjälp av denna nya funktion har codecs lagts till för uppgifter som inte är direkt relaterade till Unicode. Exempelvis har codecs lagts till för uu-kodning, MIME:s base64-kodning och komprimering med modulen zlib
:
>>> s = """Here is a lengthy piece of redundant, overly verbose,
... and repetitive text.
... """
>>> data = s.encode('zlib')
>>> data
'x\x9c\r\xc9\xc1\r\x80 \x10\x04\xc0?Ul...'
>>> data.decode('zlib')
'Here is a lengthy piece of redundant, overly verbose,\nand repetitive text.\n'
>>> print s.encode('uu')
begin 666 <data>
M2&5R92!I<R!A(&QE;F=T:'D@<&EE8V4@;V8@<F5D=6YD86YT+"!O=F5R;'D@
>=F5R8F]S92P*86YD(')E<&5T:71I=F4@=&5X="X*
end
>>> "sheesh".encode('rot-13')
'furrfu'
För att konvertera en klassinstans till Unicode kan en __unicode__()
-metod definieras av en klass, analogt med __str__()
.
encode()
, decode()
, och __unicode__()
implementerades av Marc-André Lemburg. Ändringarna för att stödja intern användning av UCS-4 implementerades av Fredrik Lundh och Martin von Löwis.
Se även
- PEP 261 - Stöd för ”breda” Unicode-tecken
Skriven av Paul Prescod.
PEP 227: Nästlade scopes¶
I Python 2.1 lades statiskt nästlade scopes till som en valfri funktion, som kunde aktiveras med ett from __future__ import nested_scopes
-direktiv. I 2.2 behöver nästlade scopes inte längre aktiveras särskilt, utan finns nu alltid. Resten av det här avsnittet är en kopia av beskrivningen av nested scopes från mitt dokument ”What’s New in Python 2.1”; om du läste det när 2.1 kom ut kan du hoppa över resten av det här avsnittet.
Den största förändringen som introducerades i Python 2.1, och som slutfördes i 2.2, är Pythons scoping-regler. I Python 2.0 finns det vid varje given tidpunkt högst tre namnrymder som används för att leta upp variabelnamn: lokalt, modulnivå och det inbyggda namnrymden. Detta förvånade ofta människor eftersom det inte stämde överens med deras intuitiva förväntningar. Till exempel fungerar inte en nästlad rekursiv funktionsdefinition:
def f():
...
def g(value):
...
return g(value-1) + 1
...
Funktionen g()
kommer alltid att ge upphov till ett NameError
-undantag, eftersom bindningen av namnet g
inte finns i vare sig dess lokala namnrymd eller i namnrymden på modulnivå. Detta är inte mycket av ett problem i praktiken (hur ofta definierar man rekursivt inre funktioner på det här sättet?), men det gjorde det också klumpigare att använda lambda
-uttrycket, och det var ett problem i praktiken. I kod som använder lambda
kan man ofta hitta lokala variabler som kopieras genom att de skickas som standardvärden för argument.
def find(self, name):
"Return list of any entries equal to 'name'"
L = filter(lambda x, name=name: x == name,
self.list_attribute)
return L
Läsbarheten hos Python-kod skriven i en starkt funktionell stil blir därför mycket lidande.
Den mest betydande förändringen i Python 2.2 är att statisk scoping har lagts till i språket för att lösa detta problem. Som en första effekt är standardargumentet namn=namn
nu onödigt i exemplet ovan. Enkelt uttryckt, när ett givet variabelnamn inte tilldelas ett värde inom en funktion (genom en tilldelning, eller genom def
, class
, eller import
), kommer referenser till variabeln att sökas i det lokala namnrymden i det omslutande scopet. En mer detaljerad förklaring av reglerna, och en dissektion av implementationen, finns i PEP.
Denna ändring kan orsaka vissa kompatibilitetsproblem för kod där samma variabelnamn används både på modulnivå och som en lokal variabel inom en funktion som innehåller ytterligare funktionsdefinitioner. Detta verkar dock ganska osannolikt, eftersom sådan kod skulle ha varit ganska förvirrande att läsa från början.
En bieffekt av ändringen är att from module import *
och exec
-uttrycken har blivit olagliga inom en funktionsomfång under vissa förhållanden. Python-referensmanualen har hela tiden sagt att endast from module import *
är lagligt på den högsta nivån i en modul, men CPython-tolken har aldrig tidigare tillämpat detta. Som en del av implementeringen av nästlade scope måste kompilatorn som förvandlar Python-källkod till bytecodes generera annan kod för att komma åt variabler i ett innehållande scope. from module import *
och exec
gör det omöjligt för kompilatorn att räkna ut detta, eftersom de lägger till namn i det lokala namnrymden som är okända vid kompileringstillfället. Därför, om en funktion innehåller funktionsdefinitioner eller lambda
uttryck med fria variabler, kommer kompilatorn att flagga detta genom att skapa ett SyntaxError
undantag.
För att göra den föregående förklaringen lite tydligare, här är ett exempel:
x = 1
def f():
# Nästa rad är ett syntaxfel
exec 'x=2'
def g():
return x
Rad 4 som innehåller exec
-satsen är ett syntaxfel, eftersom exec
skulle definiera en ny lokal variabel med namnet x
vars värde ska nås av g()
.
Detta borde inte vara någon större begränsning, eftersom exec
sällan används i den mesta Python-koden (och när det används är det ofta ett tecken på dålig design).
Se även
- PEP 227 - Statiskt nästlade scopes
Skriven och implementerad av Jeremy Hylton.
Nya och förbättrade moduler¶
Modulen
xmlrpclib
är ett bidrag till standardbiblioteket från Fredrik Lundh och ger stöd för att skriva XML-RPC-klienter. XML-RPC är ett enkelt protokoll för fjärrproceduranrop som bygger på HTTP och XML. Följande utdrag hämtar till exempel en lista med RSS-kanaler från O’Reilly Network och listar sedan de senaste rubrikerna för en kanal:import xmlrpclib s = xmlrpclib.server( 'http://www.oreillynet.com/meerkat/xml-rpc/server.php') kanaler = s.meerkat.getChannels() # kanaler är en lista med ordböcker, så här: # [{'id': 4, 'title': 'Freshmeat Daily News'} # {'id': 190, 'title': '32Bits Online'}, # {'id': 4549, 'title': '3DGamers'}, ... ] # Hämta objekten för en kanal objekt = s.meerkat.getItems( {'kanal': 4} ) # "items" är en annan lista med ordböcker, så här: # [{'link': 'http://freshmeat.net/releases/52719/', # 'description': 'Ett verktyg som konverterar HTML till XSL FO.', # 'title': 'html2fo 0.3 (Standard)'}, ... ]
Modulen
SimpleXMLRPCServer
gör det enkelt att skapa enkla XML-RPC-servrar. Se http://xmlrpc.scripting.com/ för mer information om XML-RPC.Den nya modulen
hmac
implementerar HMAC-algoritmen som beskrivs av RFC 2104. (Bidrag från Gerhard Häring.)Flera funktioner som ursprungligen returnerade långa tuplar returnerar nu pseudosekvenser som fortfarande beter sig som tuplar men som också har minnesvärda attribut som
memberst_mtime
ellertm_year
. De förbättrade funktionerna inkluderarstat()
,fstat()
,statvfs()
ochfstatvfs()
i modulenos
, ochlocaltime()
,gmtime()
ochstrptime()
i modulentime
.Om du till exempel vill veta storleken på en fil med hjälp av de gamla tuplarna skulle du skriva något i stil med
file_size = os.stat(filnamn)[stat.ST_SIZE]
, men nu kan det skrivas tydligare somfile_size = os.stat(filnamn).st_size
.Den ursprungliga korrigeringen för denna funktion gjordes av Nick Mathewson.
Python-profileraren har genomgått en omfattande omarbetning och olika fel i dess utdata har korrigerats. (Bidrag från Fred L. Drake, Jr. och Tim Peters.)
Modulen
socket
kan kompileras för att stödja IPv6; ange alternativet--enable-ipv6
i Pythons configure-skript. (Bidrag från Jun-ichiro ”itojun” Hagino.)Två nya formattecken har lagts till i modulen
struct
för 64-bitars heltal på plattformar som stöder C long long-typen.q
är för ett signerat 64-bitars heltal, ochQ
är för ett osignerat. Värdet returneras i Pythons long integer-typ. (Bidrag från Tim Peters.)I tolkens interaktiva läge finns en ny inbyggd funktion
help()
som använder modulenpydoc
som introducerades i Python 2.1 för att ge interaktiv hjälp.help(object)
visar all tillgänglig hjälptext om object.help()
utan argument placerar dig i ett online-hjälpverktyg, där du kan ange namnen på funktioner, klasser eller moduler för att läsa deras hjälptext. (Bidrag från Guido van Rossum, som använder Ka-Ping Yee:s modulpydoc
)Olika buggfixar och prestandaförbättringar har gjorts i SRE-motorn som ligger till grund för modulen
re
. Till exempel har funktionernare.sub()
ochre.split()
skrivits om i C. En annan patch som har bidragit snabbar upp vissa Unicode-teckenintervall med en faktor två, och en nyfinditer()
-metod som returnerar en iterator över alla icke-överlappande matchningar i en given sträng. (SRE underhålls av Fredrik Lundh. BIGCHARSET-patchen är ett bidrag från Martin von Löwis)Modulen
smtplib
stöder nu RFC 2487, ”Secure SMTP over TLS”, så det är nu möjligt att kryptera SMTP-trafiken mellan ett Python-program och den e-posttransportagent som får ett meddelande.smtplib
stöder också SMTP-autentisering. (Bidrag från Gerhard Häring.)Modulen
imaplib
, som underhålls av Piers Lauder, har stöd för flera nya tillägg: NAMESPACE-tillägget som definieras i RFC 2342, SORT, GETACL och SETACL. (Bidrag från Anthony Baxter och Michel Pelletier.)Modulen
rfc822
:s parsning av e-postadresser är nu kompatibel med RFC 2822, en uppdatering av RFC 822. (Modulens namn kommer inte att ändras tillrfc2822
.) Ett nytt paket,email
, har också lagts till för parsning och generering av e-postmeddelanden. (Bidraget kommer från Barry Warsaw och är ett resultat av hans arbete med Mailman)Modulen
difflib
innehåller nu en ny klassDiffer
för att producera mänskligt läsbara listor över förändringar (ett ”delta”) mellan två sekvenser av textrader. Det finns också två generatorfunktioner,ndiff()
ochrestore()
, som returnerar ett delta från två sekvenser respektive en av originalsekvenserna från ett delta. (Grunt-arbete utfört av David Goodger, från ndiff.py-kod av Tim Peters som sedan gjorde generatoriseringen)Nya konstanter
ascii_letters
,ascii_lowercase
ochascii_uppercase
har lagts till i modulenstring
. Det fanns flera moduler i standardbiblioteket som användestring.letters
för att betyda intervallen A-Za-z, men det antagandet är felaktigt när lokalspråk används, eftersomstring.letters
varierar beroende på uppsättningen av lagliga tecken som definieras av det aktuella lokalspråket. De buggiga modulerna har alla åtgärdats så att de använderascii_letters
istället. (Rapporterad av en okänd person; åtgärdad av Fred L. Drake, Jr.)Modulen
mimetypes
gör det nu enklare att använda alternativa MIME-typdatabaser genom tillägget av en klassMimeTypes
, som tar emot en lista med filnamn som skall analyseras. (Bidrag från Fred L. Drake, Jr.)En
Timer
-klass lades till ithreading
-modulen som gör det möjligt att schemalägga en aktivitet till en viss tidpunkt i framtiden. (Bidrag från Itamar Shtull-Trauring.)
Ändringar och korrigeringar i tolkprogrammet¶
En del av ändringarna påverkar bara personer som arbetar med Python-tolken på C-nivå, eftersom de skriver Python-tilläggsmoduler, bäddar in tolken eller bara hackar på själva tolken. Om du bara skriver Python-kod kommer ingen av de förändringar som beskrivs här att påverka dig särskilt mycket.
Profilerings- och spårningsfunktioner kan nu implementeras i C, som kan arbeta i mycket högre hastigheter än Python-baserade funktioner och bör minska omkostnaderna för profilering och spårning. Detta kommer att vara av intresse för författare av utvecklingsmiljöer för Python. Två nya C-funktioner har lagts till i Pythons API,
PyEval_SetProfile()
ochPyEval_SetTrace()
. De befintliga funktionernasys.setprofile()
ochsys.settrace()
finns fortfarande kvar och har helt enkelt ändrats för att använda det nya gränssnittet på C-nivå. (Bidrag från Fred L. Drake, Jr.)Ytterligare ett API på låg nivå, främst av intresse för implementatörer av Python-debuggar och utvecklingsverktyg, har lagts till.
PyInterpreterState_Head()
ochPyInterpreterState_Next()
låter en anropare gå igenom alla befintliga tolkobjekt;PyInterpreterState_ThreadHead()
ochPyThreadState_Next()
tillåter loopning över alla trådstatusar för en given tolk. (Bidrag från David Beazley.)Gränssnittet på C-nivå till skräpsamlaren har ändrats för att göra det lättare att skriva tilläggstyper som stöder skräpsamling och för att felsöka felaktig användning av funktionerna. Olika funktioner har lite olika semantik, så ett antal funktioner måste döpas om. Tillägg som använder det gamla API:et kommer fortfarande att kompileras men kommer inte att delta i garbage collection, så att uppdatera dem för 2.2 bör anses ha ganska hög prioritet.
Utför följande steg för att uppgradera en tilläggsmodul till det nya API:et:
Byt namn på
Py_TPFLAGS_GC
tillPy_TPFLAGS_HAVE_GC
.- Använd
PyObject_GC_New()
ellerPyObject_GC_NewVar()
för att allokera objekt och
PyObject_GC_Del()
för att avallokera dem.
- Använd
Byt namn på
PyObject_GC_Init()
tillPyObject_GC_Track()
ochPyObject_GC_Fini()
tillPyObject_GC_UnTrack()
.Ta bort
PyGC_HEAD_SIZE
från beräkningar av objektstorlek.Ta bort anrop till
PyObject_AS_GC()
ochPyObject_FROM_GC()
.En ny
et
formatsekvens lades till iPyArg_ParseTuple()
;et
tar både en parameter och ett kodningsnamn, och konverterar parametern till den givna kodningen om parametern visar sig vara en Unicode-sträng, eller lämnar den ifred om det är en 8-bitars sträng, och antar att den redan är i önskad kodning. Detta skiljer sig från formattecknetes
, som antar att 8-bitars strängar är i Pythons standard ASCII-kodning och konverterar dem till den angivna nya kodningen. (Bidrag från M.-A. Lemburg, och används för MBCS-stödet på Windows som beskrivs i följande avsnitt.)En annan argumentparsingfunktion,
PyArg_UnpackTuple()
, har lagts till som är enklare och förmodligen snabbare. Istället för att ange en formatsträng anger anroparen helt enkelt det minsta och största antalet argument som förväntas, och en uppsättning pekare till PyObject*-variabler som ska fyllas i med argumentvärden.Två nya flaggor
METH_NOARGS
ochMETH_O
finns tillgängliga i metoddefinitionstabeller för att förenkla implementeringen av metoder utan argument eller med ett enda otypat argument. Anrop av sådana metoder är effektivare än anrop av en motsvarande metod som använderMETH_VARARGS
. Dessutom är den gamlaMETH_OLDARGS
-stilen att skriva C-metoder nu officiellt föråldrad.Två nya omslagsfunktioner,
PyOS_snprintf()
ochPyOS_vsnprintf()
lades till för att tillhandahålla plattformsoberoende implementationer för de relativt nya C lib API:ernasnprintf()
ochvsnprintf()
. Till skillnad från standardfunktionernasprintf()
ochvsprintf()
kontrollerar Python-versionerna gränserna för den buffert som används för att skydda mot buffertöverskridanden. (Bidrag från M.-A. Lemburg.)Funktionen
_PyTuple_Resize()
har förlorat en oanvänd parameter, så nu tar den 2 parametrar istället för 3. Det tredje argumentet användes aldrig, och kan helt enkelt kasseras när kod från tidigare versioner portas till Python 2.2.
Övriga ändringar och korrigeringar¶
Som vanligt fanns det en massa andra förbättringar och buggfixar utspridda i hela källträdet. En sökning genom CVS-ändringsloggarna visar att det fanns 527 korrigeringar och 683 buggfixar mellan Python 2.1 och 2.2; 2.2.1 tillämpade 139 korrigeringar och fixade 143 buggar; 2.2.2 tillämpade 106 korrigeringar och fixade 82 buggar. Dessa siffror är sannolikt underskattningar.
Några av de mer anmärkningsvärda förändringarna är:
Koden för MacOS-porten för Python, som underhålls av Jack Jansen, finns nu i Pythons CVS-huvudträd och många ändringar har gjorts för att stödja MacOS X.
Den mest betydande förändringen är möjligheten att bygga Python som ett ramverk, vilket aktiveras genom att ange alternativet
--enable-framework
till configure-skriptet när Python kompileras. Enligt Jack Jansen, ”Detta installerar en fristående Python-installation plus OS X-ramverket ”glue” i/Library/Frameworks/Python.framework
(eller annan valfri plats). För närvarande finns det inte mycket omedelbar nytta med detta (det finns faktiskt en nackdel i att du måste ändra din PATH för att kunna hitta Python), men det är grunden för att skapa en fullfjädrad Python-applikation, porta MacPython IDE, eventuellt använda Python som ett standard OSA-skriptspråk och mycket mer.”De flesta av MacPythons verktygslådemoduler, som har gränssnitt mot MacOS API:er som windowing, QuickTime, scripting, etc. har portats till OS X, men de har lämnats okommenterade i
setup.py
. Personer som vill experimentera med dessa moduler kan kommentera bort dem manuellt.Nyckelordsargument som skickas till inbyggda funktioner som inte tar emot dem orsakar nu ett
TypeError
-undantag med meddelandet ”funktion tar inga nyckelordsargument”.Svaga referenser, som lades till i Python 2.1 som en tilläggsmodul, är nu en del av kärnan eftersom de används i implementeringen av klasser av ny typ. Undantaget
ReferenceError
har därför flyttats från modulenweakref
till att bli ett inbyggt undantag.Ett nytt skript,
Tools/scripts/cleanfuture.py
av Tim Peters, tar automatiskt bort föråldrade__future__
-satser från Pythons källkod.Ett ytterligare flags-argument har lagts till i den inbyggda funktionen
compile()
, så att beteendet hos__future__
-satser nu kan observeras korrekt i simulerade skal, som de som presenteras av IDLE och andra utvecklingsmiljöer. Detta beskrivs i PEP 264. (Bidrag från Michael Hudson.)Den nya licensen som introducerades med Python 1.6 var inte GPL-kompatibel. Detta är åtgärdat genom några mindre textändringar i 2.2-licensen, så det är nu lagligt att bädda in Python i ett GPL-program igen. Observera att Python i sig inte är GPL, utan istället är under en licens som i huvudsak är likvärdig med BSD-licensen, precis som den alltid har varit. Licensändringarna tillämpades också på Python 2.0.1 och 2.1.1 utgåvorna.
När Python får ett Unicode-filnamn i Windows konverterar Python det nu till en MBCS-kodad sträng, som används av Microsofts fil-API:er. Eftersom MBCS uttryckligen används av fil-API:erna, visar sig Pythons val av ASCII som standardkodning vara ett irritationsmoment. På Unix används lokalens teckenuppsättning om
locale.nl_langinfo(CODESET)
är tillgänglig. (Windows-stöd har tillhandahållits av Mark Hammond med hjälp av Marc-André Lemburg. Unix-stöd har lagts till av Martin von Löwis)Stöd för stora filer är nu aktiverat i Windows. (Bidrag från Tim Peters.)
Skriptet
Tools/scripts/ftpmirror.py
analyserar nu en.netrc
-fil, om du har en sådan. (Bidrag från Mike Romberg.)Vissa egenskaper hos objektet som returneras av funktionen
xrange()
är nu föråldrade och utlöser varningar när de används; de kommer att försvinna i Python 2.3.xrange
-objekt försökte låtsas att de var fullständiga sekvenstyper genom att stödja skivning, sekvensmultiplikation och operatornin
, men dessa egenskaper användes sällan och var därför buggiga. Metodentolist()
och attributenstart
,stop
ochstep
är också föråldrade. På C-nivå har det fjärde argumentet till funktionenPyRange_New()
,repeat
, också utgått.Det fanns ett antal korrigeringar till implementationen av ordböcker, mestadels för att åtgärda potentiella dumpningar av kärnan om en ordbok innehåller objekt som i smyg ändrade sitt hashvärde eller muterade den ordbok de ingick i. Under en tid föll python-dev in i en lugn rytm där Michael Hudson hittade ett fall som dumpade kärnan, Tim Peters fixade buggen, Michael hittade ett annat fall och så gick det runt och runt.
På Windows kan Python nu kompileras med Borland C tack vare ett antal patchar som Stephen Hansen har bidragit med, även om resultatet inte är fullt funktionellt ännu. (Men det här är ett framsteg…)
Ännu en Windows-förbättring: Wise Solutions erbjöd generöst PythonLabs att använda deras InstallerMaster 8.1-system. Tidigare PythonLabs Windows-installatörer använde Wise 5.0a, som började visa sin ålder. (Paketerat av Tim Peters.)
Filer som slutar på
.pyw
kan nu importeras i Windows..pyw
är något som bara finns i Windows och används för att indikera att ett skript måste köras med PYTHONW.EXE istället för PYTHON.EXE för att förhindra att en DOS-konsol dyker upp för att visa utdata. Denna patch gör det möjligt att importera sådana skript, ifall de också kan användas som moduler. (Implementerad av David Bolen.)På plattformar där Python använder C-funktionen
dlopen()
för att ladda tilläggsmoduler är det nu möjligt att ställa in flaggorna som används avdlopen()
med hjälp av funktionernasys.getdlopenflags()
ochsys.setdlopenflags()
. (Bidrag från Bram Stolk.)Den inbyggda funktionen
pow()
har inte längre stöd för 3 argument när flyttal anges.pow(x, y, z)
returnerar(x**y) % z
, men detta är aldrig användbart för flyttal och slutresultatet varierar oförutsägbart beroende på plattform. Ett anrop sompow(2.0, 8.0, 7.0)
kommer nu att ge upphov till ettTypeError
undantag.
Tack till¶
Författaren vill tacka följande personer för förslag, korrigeringar och hjälp med olika utkast till denna artikel: Fred Bremmer, Keith Briggs, Andrew Dalke, Fred L. Drake, Jr, Carel Fellinger, David Goodger, Mark Hammond, Stephen Hansen, Michael Hudson, Jack Jansen, Marc-André Lemburg, Martin von Löwis, Fredrik Lundh, Michael McLay, Nick Mathewson, Paul Moore, Gustavo Niemeyer, Don O’Donnell, Joonas Paalasma, Tim Peters, Jens Quade, Tom Reinhardt, Neil Schemenauer, Guido van Rossum, Greg Ward, Edward Welbourne.