collections
— Datatyper för behållare¶
Källkod: Lib/collections/__init__.py
Denna modul implementerar specialiserade datatyper för containrar som ger alternativ till Pythons inbyggda containrar för allmänna ändamål, dict
, list
, set
och tuple
.
fabriksfunktion för att skapa tuple-subklasser med namngivna fält |
|
listliknande behållare med snabba tillägg och öppningar i båda ändar |
|
|
diktliknande klass för att skapa en enda vy av flera mappningar |
dict-underklass för räkning av hashable-objekt |
|
dict-underklass som kommer ihåg i vilken ordning posterna lades till |
|
dict-underklass som anropar en fabriksfunktion för att leverera saknade värden |
|
omslag runt ordboksobjekt för enklare underklassning av ordböcker |
|
omslag runt listobjekt för enklare underklassning av listor |
|
omslag runt strängobjekt för enklare underklassning av strängar |
ChainMap
-objekt¶
Tillagd i version 3.3.
En ChainMap
-klass tillhandahålls för att snabbt länka ett antal mappningar så att de kan behandlas som en enda enhet. Det är ofta mycket snabbare än att skapa en ny ordbok och köra flera update()
-anrop.
Klassen kan användas för att simulera nästlade scopes och är användbar i templating.
- class collections.ChainMap(*maps)¶
En
ChainMap
grupperar flera dicts eller andra mappningar tillsammans för att skapa en enda, uppdaterbar vy. Om inga mappningar anges, tillhandahålls en enda tom ordbok så att en ny kedja alltid har minst en mappning.De underliggande mappningarna lagras i en lista. Listan är offentlig och kan nås eller uppdateras med hjälp av attributet maps. Det finns inget annat tillstånd.
Lookups söker igenom de underliggande mappningarna successivt tills en nyckel hittas. Skrivningar, uppdateringar och borttagningar påverkar däremot bara den första mappningen.
En
ChainMap
innehåller de underliggande mappningarna genom referens. Så om en av de underliggande mappningarna uppdateras, kommer dessa ändringar att återspeglas iChainMap
.Alla de vanliga metoderna för ordböcker stöds. Dessutom finns ett maps-attribut, en metod för att skapa nya underkontexter och en egenskap för att komma åt alla mappningar utom den första:
- maps¶
En lista med mappningar som kan uppdateras av användaren. Listan är ordnad från först sökta till sist sökta. Det är det enda lagrade tillståndet och kan modifieras för att ändra vilka mappningar som ska sökas. Listan bör alltid innehålla minst en mappning.
- new_child(m=None, **kwargs)¶
Returnerar en ny
ChainMap
som innehåller en ny karta följd av alla kartor i den aktuella instansen. Omm
specificeras blir det den nya kartan längst fram i listan över mappningar; om den inte specificeras används en tom dict, så att ett anrop tilld.new_child()
är likvärdigt med:ChainMap({}, *d.maps)
. Om några nyckelordsargument anges uppdaterar de den map som skickas eller en ny tom dict. Den här metoden används för att skapa underkontexter som kan uppdateras utan att ändra värden i någon av de överordnade mappningarna.Ändrad i version 3.4: Den valfria parametern
m
har lagts till.Ändrad i version 3.10: Stöd för sökordsargument har lagts till.
- parents¶
Egenskap som returnerar en ny
ChainMap
som innehåller alla kartor i den aktuella instansen utom den första. Detta är användbart för att hoppa över den första kartan i sökningen. Användningsfallen liknar dem för nyckelordetnonlocal
som används i nested scopes. Användningsfallen är också parallella med dem för den inbyggda funktionensuper()
. En referens tilld.parents
är likvärdig med:ChainMap(*d.maps[1:])
.
Observera att iterationsordningen för en
ChainMap
bestäms genom att skanna mappningarna från sist till först:>>> baseline = {'music': 'bach', 'art': 'rembrandt'} >>> adjustments = {'art': 'van gogh', 'opera': 'carmen'} >>> list(ChainMap(adjustments, baseline)) ['music', 'art', 'opera']
Detta ger samma ordning som en serie
dict.update()
-anrop som börjar med den sista mappningen:>>> combined = baseline.copy() >>> combined.update(adjustments) >>> list(combined) ['music', 'art', 'opera']
Ändrad i version 3.9: Lagt till stöd för operatorerna
|
och|=
, specificerat i PEP 584.
Se även
Klassen MultiContext i Enthoughts CodeTools-paket har alternativ för att stödja skrivning till alla mappningar i kedjan.
Djangos Context class för templating är en skrivskyddad kedja av mappningar. Den innehåller också pushing och popping av kontexter som liknar metoden
new_child()
och egenskapenparents
.Receptet Nested Contexts har alternativ för att styra om skrivningar och andra mutationer endast ska gälla den första mappningen eller alla mappningar i kedjan.
ChainMap
Exempel och recept¶
I detta avsnitt visas olika sätt att arbeta med kedjade kartor.
Exempel på simulering av Pythons interna lookup-kedja:
import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))
Exempel på att låta användarspecifika kommandoradsargument ha företräde framför miljövariabler som i sin tur har företräde framför standardvärden:
import os, argparse
defaults = {'color': 'red', 'user': 'guest'}
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}
combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])
Exempel på mönster för användning av klassen ChainMap
för att simulera nästlade kontexter:
c = ChainMap() # Skapa rotkontext
d = c.new_child() # Skapa ett nästlat barnkontext
e = c.new_child() # Barn till c, oberoende av d
e.maps[0] # Aktuell kontextordbok -- som Pythons locals()
e.maps[-1] # Rotkontext -- som Pythons globals()
e.parents # Omslutande kontextkedja -- som Pythons nonlocals
d['x'] = 1 # Ange värde i aktuell kontext
d['x'] # Hämta första nyckeln i kedjan av kontexter
del d['x'] # Ta bort från aktuell kontext
list(d) # Alla nästlade värden
k in d # Kontrollera alla nästlade värden
len(d) # Antal nästlade värden
d.items() # Alla nästlade objekt
dict(d) # Plattas ut till en vanlig ordbok
Klassen ChainMap
gör bara uppdateringar (skrivningar och raderingar) till den första mappningen i kedjan medan uppslagningar söker i hela kedjan. Men om djupa skrivningar och raderingar önskas är det enkelt att skapa en underklass som uppdaterar nycklar som finns djupare i kedjan:
class DeepChainMap(ChainMap):
'Variant of ChainMap that allows direct updates to inner scopes'
def __setitem__(self, key, value):
for mapping in self.maps:
if key in mapping:
mapping[key] = value
return
self.maps[0][key] = value
def __delitem__(self, key):
for mapping in self.maps:
if key in mapping:
del mapping[key]
return
raise KeyError(key)
>>> d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
>>> d['lion'] = 'orange' # update an existing key two levels down
>>> d['snake'] = 'red' # new keys get added to the topmost dict
>>> del d['elephant'] # remove an existing key one level down
>>> d # display result
DeepChainMap({'zebra': 'black', 'snake': 'red'}, {}, {'lion': 'orange'})
Counter
-objekt¶
Ett räkneverktyg tillhandahålls för att stödja praktiska och snabba räkningar. Till exempel:
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1
...
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})
>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
- class collections.Counter([iterable-or-mapping])¶
En
Counter
är endict
-underklass för att räkna hashable-objekt. Det är en samling där element lagras som nycklar i en ordbok och deras antal lagras som ordboksvärden. Antalet kan vara vilket heltalsvärde som helst, inklusive noll eller negativa värden. KlassenCounter
liknar påsar eller multisets i andra språk.Element räknas från en iterable eller initialiseras från en annan mapping (eller räknare):
>>> c = Counter() # a new, empty counter >>> c = Counter('gallahad') # a new counter from an iterable >>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping >>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
Counter-objekt har ett dictionary-gränssnitt förutom att de returnerar ett nollvärde för saknade objekt i stället för att ge upphov till ett
KeyError
:>>> c = Counter(['eggs', 'ham']) >>> c['bacon'] # count of a missing element is zero 0
Att nollställa ett räkneverk tar inte bort ett element från ett räkneverk. Använd
del
för att ta bort det helt:>>> c['sausage'] = 0 # counter entry with a zero count >>> del c['sausage'] # del actually removes the entry
Tillagd i version 3.1.
Ändrad i version 3.7: Som en underklass till
dict
ärvdeCounter
förmågan att komma ihåg inmatningsordning. Matematiska operationer på Counter-objekt bevarar också ordningen. Resultaten sorteras efter när ett element först påträffas i den vänstra operanden och sedan efter den ordning som det påträffas i den högra operanden.Counter-objekt stöder ytterligare metoder utöver de som är tillgängliga för alla ordböcker:
- elements()¶
Returnerar en iterator över element som upprepar varje element lika många gånger som dess antal. Elementen returneras i den ordning de först påträffades. Om ett elements antal är mindre än ett kommer
elements()
att ignorera det.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> sorted(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
- most_common([n])¶
Returnerar en lista med de n vanligaste elementen och deras antal från det vanligaste till det minst vanliga. Om n utelämnas eller
None
returnerarmost_common()
alla element i räknaren. Element med lika antal ordnas i den ordning som de först påträffades:>>> Counter('abracadabra').most_common(3) [('a', 5), ('b', 2), ('r', 2)]
- subtract([iterable-or-mapping])¶
Element subtraheras från en iterable eller från en annan mappning (eller räknare). Som
dict.update()
men subtraherar räkningar istället för att ersätta dem. Både ingångar och utgångar kan vara noll eller negativa.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> d = Counter(a=1, b=2, c=3, d=4) >>> c.subtract(d) >>> c Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
Tillagd i version 3.2.
- total()¶
Beräkna summan av räkningarna.
>>> c = Counter(a=10, b=5, c=0) >>> c.total() 15
Tillagd i version 3.10.
De vanliga ordboksmetoderna är tillgängliga för
Counter
-objekt, förutom två som fungerar annorlunda för räknare.- update([iterable-or-mapping])¶
Element räknas från en iterable eller läggs till från en annan mappning (eller räknare). Som
dict.update()
men lägger till räkningar istället för att ersätta dem. Dessutom förväntas iterable vara en sekvens av element, inte en sekvens av par av typen(nyckel, värde)
.
Counters stöder omfattande jämförelseoperatorer för jämlikhet, delmängd och övermängdsrelationer: ==
, !=
, <
, <=
, >
, >=
. Alla dessa tester behandlar saknade element som om de har noll i antal, så att Counter(a=1) == Counter(a=1, b=0)
returnerar sant.
Ändrad i version 3.10: Rika jämförelseoperationer har lagts till.
Ändrad i version 3.10: I likhetstester behandlas saknade element som om de hade noll räkningar. Tidigare ansågs Counter(a=3)
och Counter(a=3, b=0)
vara skilda.
Vanliga mönster för att arbeta med Counter
-objekt:
c.total() # summa av alla räkningar
c.clear() # återställ alla räkningar
list(c) # lista unika element
set(c) # konvertera till en uppsättning
dict(c) # konvertera till en vanlig ordbok
c.items() # tillgång till paren (elem, cnt)
Counter(dict(list_of_pairs)) # konvertera från en lista med (elem, cnt)-par
c.most_common()[:-n-1:-1] # n minst gemensamma element
+c # ta bort noll och negativa räkningar
Flera matematiska operationer finns för att kombinera Counter
-objekt för att producera multisets (räknare som har antal större än noll). Addition och subtraktion kombinerar räknare genom att addera eller subtrahera räknevärdena för motsvarande element. Intersection och union returnerar minimum och maximum av motsvarande räkningar. Equality och inclusion jämför motsvarande räkningar. Varje operation kan acceptera inmatningar med signerade räkningar, men utmatningen kommer att utesluta resultat med räkningar på noll eller mindre.
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d # add two counters together: c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d # intersection: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d # union: max(c[x], d[x])
Counter({'a': 3, 'b': 2})
>>> c == d # equality: c[x] == d[x]
False
>>> c <= d # inclusion: c[x] <= d[x]
False
Unary addition och subtraction är genvägar för att addera en tom räknare eller subtrahera från en tom räknare.
>>> c = Counter(a=2, b=-4)
>>> +c
Counter({'a': 2})
>>> -c
Counter({'b': 4})
Tillagd i version 3.3: Stöd för unary plus, unary minus och in-place multiset-operationer har lagts till.
Anteckning
Räknare utformades i första hand för att fungera med positiva heltal för att representera löpande räkningar, men man var noga med att inte i onödan utesluta användningsfall som behövde andra typer eller negativa värden. För att hjälpa till med dessa användningsfall dokumenterar detta avsnitt minimiintervall och typbegränsningar.
Klassen
Counter
är i sig en dictionary-subklass utan några restriktioner för dess nycklar och värden. Värdena är avsedda att vara siffror som representerar antal, men du kan lagra vad som helst i värdefältet.Metoden
most_common()
kräver endast att värdena är ordningsbara.För in-place-operationer som
c[key] += 1
behöver värdetypen bara stödja addition och subtraktion. Så bråk, flyttal och decimaler skulle fungera och negativa värden stöds. Detsamma gäller även förupdate()
ochsubtract()
som tillåter negativa och nollvärden för både in- och utdata.Multiset-metoderna är endast avsedda för användningsfall med positiva värden. Ingångsvärdena kan vara negativa eller noll, men endast utgångar med positiva värden skapas. Det finns inga typbegränsningar, men värdetypen måste stödja addition, subtraktion och jämförelse.
Metoden
elements()
kräver heltalsräkningar. Den ignorerar noll och negativa räkningar.
Se även
Bag-klass i Smalltalk.
Wikipedia-inlägg för Multisets.
C++ multisets handledning med exempel.
För matematiska operationer på flermängder och deras användningsområden, se Knuth, Donald. The Art of Computer Programming Volume II, avsnitt 4.6.3, övning 19.
För att räkna upp alla distinkta fleruppsättningar av en viss storlek över en viss uppsättning element, se
itertools.combinations_with_replacement()
:map(Räknare, kombinationer_med_ersättning('ABC', 2)) # --> AA AB AC BB BC CC
deque
-objekt¶
- class collections.deque([iterable[, maxlen]])¶
Returnerar ett nytt deque-objekt som initierats från vänster till höger (med
append()
) med data från iterable. Om iterable inte anges är det nya deque-objektet tomt.Deques är en generalisering av staplar och köer (namnet uttalas ”deck” och är en förkortning av ”double-ended queue”). Deques stöder trådsäkra, minneseffektiva appends och pops från vardera sidan av deque med ungefär samma O(1) prestanda i båda riktningarna.
Även om
list
-objekt stöder liknande operationer är de optimerade för snabba operationer med fasta längder och medför O(n) minnesförflyttningskostnader för operationernapop(0)
ochinsert(0, v)
som ändrar både storleken och positionen för den underliggande datarepresentationen.Om maxlen inte anges eller är
None
, kan deques växa till godtycklig längd. I annat fall är deque begränsad till den angivna maximala längden. När en deque med begränsad längd är full, när nya objekt läggs till, kasseras ett motsvarande antal objekt från den motsatta änden. Deques med begränsad längd har en funktionalitet som liknar filtrettail
i Unix. De är också användbara för att spåra transaktioner och andra datapooler där endast den senaste aktiviteten är av intresse.Deque-objekt stöder följande metoder:
- append(x)¶
Lägg till x på höger sida av deque.
- appendleft(x)¶
Lägg till x på vänster sida av deque.
- clear()¶
Ta bort alla element från deque och lämna den med längd 0.
- copy()¶
Skapa en ytlig kopia av deque.
Tillagd i version 3.5.
- count(x)¶
Räkna antalet deque-element som är lika med x.
Tillagd i version 3.2.
- extend(iterable)¶
Förläng höger sida av deque genom att lägga till element från iterable-argumentet.
- extendleft(iterable)¶
Förläng vänster sida av deque genom att lägga till element från iterable. Observera att serien av vänstra appends resulterar i att ordningen på elementen i iterable-argumentet vänds.
- index(x[, start[, stop]])¶
Returnerar positionen för x i deque (vid eller efter index start och före index stop). Returnerar den första matchningen eller ger
ValueError
om den inte hittas.Tillagd i version 3.5.
- insert(i, x)¶
Sätt in x i deque på position i.
Om införandet skulle leda till att en avgränsad deque växer bortom maxlen, kommer ett
IndexError
att uppstå.Tillagd i version 3.5.
- pop()¶
Tar bort och returnerar ett element från höger sida av deque. Om inga element finns, uppstår ett
IndexError
.
- popleft()¶
Tar bort och returnerar ett element från vänster sida av deque. Om inga element finns, uppstår ett
IndexError
.
- remove(value)¶
Tar bort den första förekomsten av värde. Om det inte hittas, uppstår ett
ValueError
.
- reverse()¶
Vänd elementen i deque på plats och returnera sedan
None
.Tillagd i version 3.2.
- rotate(n=1)¶
Rotera dekanen n steg åt höger. Om n är negativ, rotera till vänster.
När deque inte är tom är rotation ett steg åt höger likvärdigt med
d.appendleft(d.pop())
, och rotation ett steg åt vänster är likvärdigt medd.append(d.popleft())
.
Deque-objekt har också ett skrivskyddat attribut:
- maxlen¶
Maximal storlek på en deque eller
None
om den är obegränsad.Tillagd i version 3.1.
Förutom ovanstående stöder deques iteration, pickling, len(d)
, reversed(d)
, copy.copy(d)
, copy.deepcopy(d)
, medlemskapstestning med operatorn in
och subskriptreferenser som d[0]
för åtkomst till det första elementet. Indexerad åtkomst är O(1) i båda ändar men saktar ner till O(n) i mitten. För snabb slumpmässig åtkomst, använd listor istället.
Från och med version 3.5 har deques stöd för __add__()
, __mul__()
och __imul__()
.
Exempel:
>>> from collections import deque
>>> d = deque('ghi') # make a new deque with three items
>>> for elem in d: # iterate over the deque's elements
... print(elem.upper())
G
H
I
>>> 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']
>>> d[0] # peek at leftmost item
'g'
>>> d[-1] # peek at rightmost item
'i'
>>> list(reversed(d)) # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d # search the deque
True
>>> d.extend('jkl') # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1) # right rotation
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1) # left rotation
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> deque(reversed(d)) # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear() # empty the deque
>>> d.pop() # cannot pop from an empty deque
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
d.pop()
IndexError: pop from an empty deque
>>> d.extendleft('abc') # extendleft() reverses the input order
>>> d
deque(['c', 'b', 'a'])
deque
Recept¶
I detta avsnitt visas olika sätt att arbeta med deques.
Deques med begränsad längd ger funktionalitet som liknar filtret tail
i Unix:
def tail(filnamn, n=10):
'Returnera de sista n raderna i en fil'
med open(filnamn) som f:
returnera deque(f, n)
Ett annat sätt att använda deques är att upprätthålla en sekvens av nyligen tillagda element genom att appendiera till höger och poppa till vänster:
def glidande_medelvärde(iterabel, n=3):
# moving_average([40, 30, 50, 46, 39, 44]) --> 40,0 42,0 45,0 43,0
# https://en.wikipedia.org/wiki/Moving_average
it = iter(iterabel)
d = deque(itertools.islice(it, n-1))
d.appendleft(0)
s = summa(d)
för elem i it:
s += elem - d.popleft()
d.append(elem)
ger s / n
En round-robin schemaläggare kan implementeras med inmatningsiteratorer lagrade i en deque
. Värden erhålls från den aktiva iteratorn i position noll. Om den iteratorn är uttömd kan den tas bort med popleft()
; annars kan den cyklas tillbaka till slutet med rotate()
-metoden:
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
iteratorer = deque(map(iter, iterables))
while iterators:
försök:
while True:
yield next(iteratorer[0])
iteratorer.rotera(-1)
except StopIteration:
# Ta bort en uttömd iterator.
iteratorer.popleft()
Metoden rotate()
ger ett sätt att implementera deque
skivning och borttagning. Till exempel, en ren Python-implementering av del d[n]
förlitar sig på rotate()
-metoden för att positionera element som ska poppas:
def delete_nth(d, n):
d.rotera(-n)
d.popleft()
d.rotera(n)
För att implementera deque
slicing, använd ett liknande tillvägagångssätt med rotate()
för att föra ett målelement till vänster sida av deque. Ta bort gamla poster med popleft()
, lägg till nya poster med extend()
, och vänd sedan rotationen. Med mindre variationer på detta tillvägagångssätt är det lätt att implementera stackmanipulationer i Forth-stil som dup
, drop
, wap
, over
, pick
, rot
och roll
.
defaultdict
-objekt¶
- class collections.defaultdict(default_factory=None, /[, ...])¶
Returnerar ett nytt ordboksliknande objekt.
defaultdict
är en subklass av den inbyggdadict
-klassen. Den åsidosätter en metod och lägger till en skrivbar instansvariabel. Resterande funktionalitet är densamma som för klassendict
och dokumenteras inte här.Det första argumentet anger det initiala värdet för attributet
default_factory
; standardvärdet ärNone
. Alla återstående argument behandlas på samma sätt som om de skickades tilldict
-konstruktören, inklusive nyckelordsargument.defaultdict
-objekt stöder följande metod utöver de vanligadict
-operationerna:- __missing__(key)¶
Om attributet
default_factory
ärNone
, utlöses ettKeyError
undantag med key som argument.Om
default_factory
inte ärNone
anropas den utan argument för att ange ett standardvärde för den angivna key, detta värde infogas i ordlistan för key och returneras.Om anrop av
default_factory
ger upphov till ett undantag, sprids detta undantag oförändrat.Denna metod anropas av
__getitem__()
-metoden idict
-klassen när den begärda nyckeln inte hittas; vad den returnerar eller väcker returneras eller väcks sedan av__getitem__()
.Observera att
__missing__()
inte anropas för några andra operationer än__getitem__()
. Detta innebär attget()
kommer, precis som vanliga ordböcker, att returneraNone
som standard istället för att användadefault_factory
.
defaultdict
-objekt har stöd för följande instansvariabel:- default_factory¶
Detta attribut används av metoden
__missing__()
; det initialiseras från det första argumentet till konstruktören, om det finns, eller tillNone
, om det saknas.
Ändrad i version 3.9: Lagt till operatorer för sammanslagning (
|
) och uppdatering (|=
), specificerade i PEP 584.
defaultdict
Exempel¶
Med list
som default_factory
är det enkelt att gruppera en sekvens av nyckel-värde-par till en ordbok med listor:
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
När varje nyckel påträffas för första gången finns den inte redan i mappningen, så en post skapas automatiskt med hjälp av funktionen default_factory
som returnerar en tom list
. Operationen list.append()
lägger sedan till värdet i den nya listan. När nycklar påträffas igen fortsätter uppslagningen normalt (listan för den nyckeln returneras) och operationen list.append()
lägger till ett annat värde i listan. Denna teknik är enklare och snabbare än motsvarande teknik som använder dict.setdefault()
:
>>> d = {}
>>> for k, v in s:
... d.setdefault(k, []).append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
Om du ställer in default_factory
till int
blir defaultdict
användbar för räkning (som en påse eller multiset på andra språk):
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]
När en bokstav först påträffas saknas den i mappningen, så funktionen default_factory
anropar int()
för att ange ett standardantal på noll. Inkrementoperationen bygger sedan upp räkningen för varje bokstav.
Funktionen int()
som alltid returnerar noll är bara ett specialfall av konstantfunktioner. Ett snabbare och mer flexibelt sätt att skapa konstantfunktioner är att använda en lambda-funktion som kan ge vilket konstant värde som helst (inte bara noll):
>>> def constant_factory(value):
... return lambda: value
...
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'
Om du ställer in default_factory
på set
blir defaultdict
användbar för att bygga en ordbok med set:
>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
... d[k].add(v)
...
>>> sorted(d.items())
[('blue', {2, 4}), ('red', {1, 3})]
namedtuple()
Fabriksfunktion för tupler med namngivna fält¶
Namngivna tupler tilldelar varje position i en tupel en betydelse och möjliggör mer läsbar och självdokumenterande kod. De kan användas överallt där vanliga tuplar används, och de ger möjlighet att komma åt fält med namn i stället för positionsindex.
- collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)¶
Returnerar en ny tuple-subklass med namnet typename. Den nya underklassen används för att skapa tuple-liknande objekt som har fält som är tillgängliga genom attributuppslagning samt indexerbara och itererbara. Instanser av subklassen har också en användbar docstring (med typename och field_names) och en användbar
__repr__()
-metod som listar tuple-innehållet i ettname=value
-format.field_names är en sekvens av strängar, t.ex.
['x', 'y']
. Alternativt kan field_names vara en enda sträng där varje fältnamn separeras med blanksteg och/eller kommatecken, t.ex.'x y'
eller'x, y'
.Alla giltiga Python-identifierare kan användas för ett fältnamn utom namn som börjar med ett understreck. Giltiga identifierare består av bokstäver, siffror och understreck men börjar inte med en siffra eller ett understreck och kan inte vara ett
nyckelord
som class, for, return, global, pass eller raise.Om rename är true ersätts ogiltiga fältnamn automatiskt med positionsnamn. Till exempel konverteras
['abc', 'def', 'ghi', 'abc']
till['abc', '_1', 'ghi', '_3']
, vilket eliminerar nyckelordetdef
och det dubbla fältnamnetabc
.defaults kan vara
None
eller en iterable av standardvärden. Eftersom fält med ett standardvärde måste komma efter fält utan ett standardvärde, tillämpas defaults på parametrarna längst till höger. Om fältnamnen till exempel är['x', 'y', 'z']
och standardvärdena är(1, 2)
, kommerx
att vara ett obligatoriskt argument,y
kommer att vara standardvärdet1
ochz
kommer att vara standardvärdet2
.Om module definieras sätts attributet
__module__
i den namngivna tupeln till det värdet.Namngivna tuple-instanser har inga ordböcker per instans, så de är lätta och kräver inte mer minne än vanliga tupler.
För att stödja pickling bör den namngivna tuple-klassen tilldelas en variabel som matchar typename.
Ändrad i version 3.1: Lagt till stöd för rename.
Ändrad i version 3.6: Parametrarna verbose och rename blev keyword-only arguments.
Ändrad i version 3.6: Parametern module har lagts till.
Ändrad i version 3.7: Parametern verbose och attributet
_source
har tagits bort.Ändrad i version 3.7: Lagt till parametern defaults och attributet
_field_defaults
.
>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)
Namngivna tupler är särskilt användbara för att tilldela fältnamn till resultattuplar som returneras av modulerna csv
eller sqlite3
:
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
print(emp.name, emp.title)
import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
print(emp.name, emp.title)
Utöver de metoder som ärvs från tuples har named tuples stöd för ytterligare tre metoder och två attribut. För att undvika konflikter med fältnamn börjar metod- och attributnamnen med ett understreck.
- classmethod somenamedtuple._make(iterable)¶
Klassmetod som skapar en ny instans från en befintlig sekvens eller iterabel.
>>> t = [11, 22] >>> Point._make(t) Point(x=11, y=22)
- somenamedtuple._asdict()¶
Returnerar en ny
dict
som mappar fältnamn till deras motsvarande värden:>>> p = Point(x=11, y=22) >>> p._asdict() {'x': 11, 'y': 22}
Ändrad i version 3.1: Returnerar en
OrderedDict
istället för en vanligdict
.Ändrad i version 3.8: Returnerar en vanlig
dict
istället för enOrderedDict
. Från och med Python 3.7 garanteras att vanliga dicts är ordnade. Om de extra funktionerna iOrderedDict
krävs, är den föreslagna lösningen att casta resultatet till önskad typ:OrderedDict(nt._asdict())
.
- somenamedtuple._replace(**kwargs)¶
Returnerar en ny instans av den namngivna tupeln genom att ersätta angivna fält med nya värden:
>>> p = Point(x=11, y=22) >>> p._replace(x=33) Point(x=33, y=22) >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())
Namngivna tupler stöds också av den generiska funktionen
copy.replace()
.Ändrad i version 3.13: Utlös
TypeError
istället förValueError
för ogiltiga nyckelordsargument.
- somenamedtuple._fields¶
Tupel med strängar som listar fältnamnen. Användbar för introspektion och för att skapa nya namngivna tupeltyper från befintliga namngivna tuplar.
>>> p._fields # view the field names ('x', 'y') >>> Color = namedtuple('Color', 'red green blue') >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields) >>> Pixel(11, 22, 128, 255, 0) Pixel(x=11, y=22, red=128, green=255, blue=0)
- somenamedtuple._field_defaults¶
Ordbok som mappar fältnamn till standardvärden.
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0]) >>> Account._field_defaults {'balance': 0} >>> Account('premium') Account(type='premium', balance=0)
Om du vill hämta ett fält vars namn lagras i en sträng använder du funktionen getattr()
:
>>> getattr(p, 'x')
11
Om du vill konvertera en ordbok till en namngiven tupel använder du dubbelstjärneoperatorn (enligt beskrivningen i Uppackning av argumentlistor):
>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)
Eftersom en named tuple är en vanlig Python-klass är det lätt att lägga till eller ändra funktionalitet med en subklass. Så här lägger du till ett beräknat fält och ett utskriftsformat med fast bredd:
>>> class Point(namedtuple('Point', ['x', 'y'])):
... __slots__ = ()
... @property
... def hypot(self):
... return (self.x ** 2 + self.y ** 2) ** 0.5
... def __str__(self):
... return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
>>> for p in Point(3, 4), Point(14, 5/7):
... print(p)
Point: x= 3.000 y= 4.000 hypot= 5.000
Point: x=14.000 y= 0.714 hypot=14.018
Den subklass som visas ovan sätter __slots__
till en tom tupel. Detta hjälper till att hålla minneskraven låga genom att förhindra skapandet av instansordböcker.
Subklassning är inte användbart för att lägga till nya, lagrade fält. Istället skapar du helt enkelt en ny namngiven tupeltyp från attributet _fields
:
>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))
Dokumentsträngar kan anpassas genom att göra direkta tilldelningar till fälten __doc__
:
>>> Book = namedtuple('Book', ['id', 'title', 'authors'])
>>> Book.__doc__ += ': Hardcover book in active collection'
>>> Book.id.__doc__ = '13-digit ISBN'
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'
Ändrad i version 3.5: Property docstrings blev skrivbara.
Se även
Se
typing.NamedTuple
för ett sätt att lägga till typhintar för namngivna tupler. Det ger också en elegant notation med hjälp av nyckelordetclass
:class Komponent(NamedTuple): part_number: int vikt: float description (beskrivning): Valfri[str] = Ingen
Se
types.SimpleNamespace()
för en föränderlig namnrymd som baseras på en underliggande ordbok i stället för en tupel.Modulen
dataclasses
innehåller en dekorator och funktioner för att automatiskt lägga till genererade specialmetoder till användardefinierade klasser.
OrderedDict
-objekt¶
Ordnade ordböcker är precis som vanliga ordböcker men har några extra funktioner som rör ordningsoperationer. De har blivit mindre viktiga nu när den inbyggda dict
-klassen har fått förmågan att komma ihåg insättningsordning (detta nya beteende blev garanterat i Python 3.7).
Vissa skillnader från dict
kvarstår fortfarande:
Den vanliga
dict
utformades för att vara mycket bra på mappningsoperationer. Att spåra insättningsordning var sekundärt.OrderedDict
utformades för att vara bra på omordningsoperationer. Utrymmeseffektivitet, iterationshastighet och prestanda för uppdateringsoperationer var sekundära.Algoritmen
OrderedDict
kan hantera frekventa omordningsoperationer bättre ändict
. Som visas i recepten nedan gör detta att den lämpar sig för implementering av olika typer av LRU-cacher.Jämlikhetsoperationen för
OrderedDict
kontrollerar matchande ordning.En vanlig
dict
kan emulera det ordningskänsliga likhetstestet medp == q and all(k1 == k2 for k1, k2 in zip(p, q))
.Metoden
popitem()
iOrderedDict
har en annan signatur. Den accepterar ett valfritt argument för att specificera vilket objekt som ska poppas.En vanlig
dict
kan efterlikna OrderedDictsod.popitem(last=True)
medd.popitem()
som garanterat öppnar det längst till höger (sista) objektet.En vanlig
dict
kan emulera OrderedDictsod.popitem(last=False)
med(k := next(iter(d)), d.pop(k))
som returnerar och tar bort det längst till vänster (första) objektet om det finns.OrderedDict
har enmove_to_end()
-metod för att effektivt flytta ett element till en slutpunkt.En vanlig
dict
kan emulera OrderedDictsod.move_to_end(k, last=True)
medd[k] = d.pop(k)
vilket flyttar nyckeln och dess associerade värde till den högra (sista) positionen.En vanlig
dict
har inte någon effektiv motsvarighet till OrderedDictsod.move_to_end(k, last=False)
som flyttar nyckeln och dess associerade värde till den vänstra (första) positionen.Fram till Python 3.8 saknade
dict
en__reversed__()
-metod.
- class collections.OrderedDict([items])¶
Returnerar en instans av en
dict
-underklass som har metoder specialiserade på att omorganisera ordningsföljden i ordböcker.Tillagd i version 3.1.
- popitem(last=True)¶
Metoden
popitem()
för ordnade lexikon returnerar och tar bort ett (nyckel, värde)-par. Paren returneras i LIFO ordning om last är sant eller FIFO ordning om false.
- move_to_end(key, last=True)¶
Flytta en befintlig key till endera änden av en ordnad ordbok. Objektet flyttas till den högra änden om last är true (standard) eller till början om last är false. Utlöser
KeyError
om nyckeln inte finns:>>> d = OrderedDict.fromkeys('abcde') >>> d.move_to_end('b') >>> ''.join(d) 'acdeb' >>> d.move_to_end('b', last=False) >>> ''.join(d) 'bacde'
Tillagd i version 3.2.
Förutom de vanliga mappningsmetoderna stöder ordnade lexikon även omvänd iteration med hjälp av reversed()
.
Likhetstester mellan OrderedDict
-objekt är ordningskänsliga och motsvarar ungefär list(od1.items())==list(od2.items())
.
Jämlikhetstester mellan OrderedDict
-objekt och andra Mapping
-objekt är okänsliga för ordning som vanliga ordböcker. Detta gör att OrderedDict
-objekt kan ersättas var som helst där en vanlig ordbok används.
Ändrad i version 3.5: Objekten, nycklarna och värdena views i OrderedDict
stöder nu omvänd iteration med reversed()
.
Ändrad i version 3.6: Med godkännandet av PEP 468, behålls ordningen för nyckelordsargument som skickas till OrderedDict
-konstruktören och dess update()
-metod.
Ändrad i version 3.9: Lagt till operatorer för sammanslagning (|
) och uppdatering (|=
), specificerade i PEP 584.
OrderedDict
Exempel och recept¶
Det är enkelt att skapa en ordnad ordboksvariant som kommer ihåg den ordning som nycklarna senast infogades. Om en ny post skriver över en befintlig post, ändras den ursprungliga inmatningspositionen och flyttas till slutet:
class LastUpdatedOrderedDict(OrderedDict):
"Lagra objekt i den ordning som nycklarna senast lades till
def __setitem__(self, nyckel, värde):
super().__setitem__(nyckel, värde)
self.move_to_end(nyckel)
En OrderedDict
skulle också vara användbar för att implementera varianter av functools.lru_cache()
:
from collections import OrderedDict
from time import time
class TimeBoundedLRU:
"LRU Cache that invalidates and refreshes old entries."
def __init__(self, func, maxsize=128, maxage=30):
self.cache = OrderedDict() # { args : (timestamp, result)}
self.func = func
self.maxsize = maxsize
self.maxage = maxage
def __call__(self, *args):
if args in self.cache:
self.cache.move_to_end(args)
timestamp, result = self.cache[args]
if time() - timestamp <= self.maxage:
return result
result = self.func(*args)
self.cache[args] = time(), result
if len(self.cache) > self.maxsize:
self.cache.popitem(last=False)
return result
klass MultiHitLRUCache:
""" LRU-cache som väntar med att cachelagra ett resultat tills
tills det har begärts flera gånger.
För att undvika att LRU-cachen töms med engångsförfrågningar,
vi inte cachelagring förrän en begäran har gjorts mer än en gång.
"""
def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):
self.requests = OrderedDict() # { uncached_key : request_count }
self.cache = OrderedDict() # { cached_key : funktion_resultat }
self.func = func
self.maxrequests = maxrequests # max antal icke-cachade förfrågningar
self.maxsize = maxsize # max antal lagrade returvärden
self.cache_after = cache_after
def __call__(self, *args):
om args i self.cache:
self.cache.move_to_end(args)
return self.cache[args]
resultat = self.func(*args)
self.requests[args] = self.requests.get(args, 0) + 1
if self.requests[args] <= self.cache_after:
self.requests.move_to_end(args)
if len(self.requests) > self.maxrequests:
self.requests.popitem(last=False)
annat:
self.requests.pop(args, None)
self.cache[args] = resultat
if len(self.cache) > self.maxsize:
self.cache.popitem(last=False)
returnera resultat
UserDict
-objekt¶
Klassen UserDict
fungerar som ett omslag runt ordboksobjekt. Behovet av denna klass har delvis ersatts av möjligheten att subklassa direkt från dict
; denna klass kan dock vara lättare att arbeta med eftersom den underliggande ordboken är tillgänglig som ett attribut.
- class collections.UserDict([initialdata])¶
Klass som simulerar en ordbok. Instansens innehåll sparas i en vanlig ordbok, som är tillgänglig via attributet
data
iUserDict
-instanser. Om initialdata anges initialiserasdata
med dess innehåll; notera att en referens till initialdata inte sparas, vilket gör att den kan användas för andra ändamål.Förutom att stödja metoder och operationer för mappningar, ger
UserDict
-instanser följande attribut:
UserList
-objekt¶
Den här klassen fungerar som ett hölje runt listobjekt. Det är en användbar basklass för dina egna listliknande klasser som kan ärva från dem och åsidosätta befintliga metoder eller lägga till nya. På så sätt kan man lägga till nya beteenden i listor.
Behovet av denna klass har delvis ersatts av möjligheten att subklassa direkt från list
; denna klass kan dock vara lättare att arbeta med eftersom den underliggande listan är tillgänglig som ett attribut.
- class collections.UserList([list])¶
Klass som simulerar en lista. Instansens innehåll sparas i en vanlig lista, som är tillgänglig via attributet
data
iUserList
-instanser. Instansens innehåll är initialt inställt på en kopia av list, med den tomma listan[]
som standard. list kan vara vilken iterabel som helst, t.ex. en riktig Python-lista eller ettUserList
-objekt.Förutom att stödja metoder och operationer för muterbara sekvenser, ger
UserList
-instanser följande attribut:
Subklassningskrav: Subklasser av UserList
förväntas erbjuda en konstruktor som kan anropas med antingen inga argument eller ett argument. Listoperationer som returnerar en ny sekvens försöker skapa en instans av den faktiska implementationsklassen. För att göra detta förutsätts att konstruktören kan anropas med en enda parameter, som är ett sekvensobjekt som används som datakälla.
Om en härledd klass inte vill uppfylla detta krav måste alla specialmetoder som stöds av denna klass åsidosättas; se källorna för information om vilka metoder som måste tillhandahållas i så fall.
UserString
-objekt¶
Klassen UserString
fungerar som ett omslag runt strängobjekt. Behovet av denna klass har delvis ersatts av möjligheten att subklassa direkt från str
; denna klass kan dock vara lättare att arbeta med eftersom den underliggande strängen är tillgänglig som ett attribut.
- class collections.UserString(seq)¶
Klass som simulerar ett strängobjekt. Instansens innehåll förvaras i ett vanligt strängobjekt, som är tillgängligt via attributet
data
iUserString
-instanser. Instansens innehåll sätts initialt till en kopia av seq. Argumentet seq kan vara vilket objekt som helst som kan konverteras till en sträng med hjälp av den inbyggda funktionenstr()
.Förutom att stödja metoder och operationer för strängar, ger
UserString
-instanser följande attribut:- data¶
Ett verkligt
str
-objekt som används för att lagra innehållet iUserString
-klassen.
Ändrad i version 3.5: Nya metoder
__getnewargs__
,__rmod__
,casefold
,format_map
,isprintable
ochmaketrans
.