python-collections — Tipo de dados do contêiner (dicionário ordenado)
Código-fonte: Lib/collections/ init.py
Este módulo implementa contêineres específicos de destino para fornecer uma alternativa aos contêineres integrados padrão do Python dict , list , set e tuple .
nome | efeito |
---|---|
nomeadotupla() | Função de fábrica para criar subclasses de tuplas nomeadas |
portanto | Um contêiner semelhante a uma lista (list), que realiza adição rápida (acrescentar) e pop-up (pop) em ambas as extremidades |
ChainMap | Uma classe de contêiner semelhante a um dicionário (dict), que coleta vários mapeamentos em uma exibição |
Contador | Uma subclasse de Dictionary que fornece funcionalidade de contagem para objetos com hash |
OrderedDict | Uma subclasse de Dictionary que preserva a ordem em que foram adicionados |
defaultdict | Uma subclasse de dicionário que fornece uma função de fábrica para fornecer um valor padrão para consultas de dicionário |
UserDict | Encapsula objetos de dicionário, simplificando a subclasse de dicionário |
Lista de usuários | Encapsula objetos de lista, simplificando a subclasse de lista |
UserString | Encapsula objetos de string, simplificando a subclasse de strings |
coleções de classes.OrderedDict([itens])
Retorna uma instância de uma subclasse dict com métodos especificamente para reorganizar a ordem lexicográfica.
3.1 novos recursos.
O método popitem() do dicionário classificado popitem(last=True)
remove e retorna um par chave-valor (chave, valor). Se o último valor for verdadeiro, os pares chave-valor serão retornados na ordem LIFO, caso contrário, os pares chave-valor serão retornados na ordem FIFO.
move_to_end(key, last=True)
move uma chave existente para qualquer extremidade do dicionário ordenado. Move a entrada para a direita se last for true (o padrão) ou para o início se last for false. Gera KeyError se a chave não existir:
>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d)
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d)
'bacde'
3.2 novos recursos.
Comparado com o método de mapeamento usual, o dicionário ordenado também fornece suporte para iteração reversa por meio de reversed().
Os testes de igualdade entre OrderedDicts são sensíveis à ordem, implementados como list(od1.items())==list(od2.items()) . Testes de igualdade para objetos OrderedDict e outros mapeamentos são testes de dicionário sensíveis à ordem. Isso permite que OrderedDict seja substituído onde qualquer dicionário pode ser usado.
Alterado na versão 3.5: As exibições de item, chave e valor do OrderedDict agora oferecem suporte à iteração reversa, via reversed().
Alterado na versão 3.6: PEP 468 favorece a preservação da ordem dos argumentos de palavra-chave passados para o construtor OrderedDict e seu método update().
Alterado na versão 3.9: Adicionados os operadores merge (|) e update (|=), conforme explicado no PEP 584
Exemplo e uso de OrderedDict
A chave de OrderedDict será classificada na ordem de inserção, não a própria chave
import collections
print "Regular dictionary"
d={
}
d['a']='A'
d['b']='B'
d['c']='C'
for k,v in d.items():
print k,v
print "\nOrder dictionary"
d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'
d1['1'] = '1'
d1['2'] = '2'
for k,v in d1.items():
print k,v
输出:
Regular dictionary
a A
c C
b B
Order dictionary
a A
b B
c C
1 1
2 2
Pode-se ver que vários elementos, como ABC, também são salvos, mas usar OrderedDict classificará de acordo com a ordem em que os elementos são colocados. Assim, os valores de saída são classificados.
Os objetos do dicionário do objeto OrderedDict, se a ordem for diferente, o Python irá tratá-los como dois objetos diferentes, veja o exemplo:
print 'Regular dictionary:'
d2={
}
d2['a']='A'
d2['b']='B'
d2['c']='C'
d3={
}
d3['c']='C'
d3['a']='A'
d3['b']='B'
print d2 == d3
print '\nOrderedDict:'
d4=collections.OrderedDict()
d4['a']='A'
d4['b']='B'
d4['c']='C'
d5=collections.OrderedDict()
d5['c']='C'
d5['a']='A'
d5['b']='B'
print d1==d2
输出:
Regular dictionary:
True
OrderedDict:
False
Veja mais alguns exemplos:
dd = {
'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
#按key排序
kd = collections.OrderedDict(sorted(dd.items(), key=lambda t: t[0]))
print kd
#按照value排序
vd = collections.OrderedDict(sorted(dd.items(),key=lambda t:t[1]))
print vd
#输出
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
Esta parte da introdução de exemplo é transferida de tooltime
É simples criar variantes de dicionário ordenadas que lembram a ordem em que as chaves foram inseridas pela última vez. Se uma nova entrada substitui uma entrada existente, a posição de inserção original é alterada e movida para o final:
class LastUpdatedOrderedDict(OrderedDict):
'Store items in the order the keys were last added'
def __setitem__(self, key, value):
super().__setitem__(key, value)
self.move_to_end(key)
Um OrderedDict também é útil para implementar variantes de functools.lru_cache():
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(0)
return result
class MultiHitLRUCache:
""" LRU cache that defers caching a result until
it has been requested multiple times.
To avoid flushing the LRU cache with one-time requests,
we don't cache until a request has been made more than once.
"""
def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1):
self.requests = OrderedDict() # { uncached_key : request_count }
self.cache = OrderedDict() # { cached_key : function_result }
self.func = func
self.maxrequests = maxrequests # max number of uncached requests
self.maxsize = maxsize # max number of stored return values
self.cache_after = cache_after
def __call__(self, *args):
if args in self.cache:
self.cache.move_to_end(args)
return self.cache[args]
result = 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(0)
else:
self.requests.pop(args, None)
self.cache[args] = result
if len(self.cache) > self.maxsize:
self.cache.popitem(0)
return result