values keys item dictionaries create python dictionary

keys - ¿Puedo hacer un dict por defecto ordenado en Python?



python dictionary of dictionaries (6)

¡Probé el dict predeterminado y descubrí que también está ordenado! tal vez fue solo una coincidencia, pero de todos modos puede usar la función ordenada:

sorted(s.items())

creo que es mas simple

Me gustaría combinar OrderedDict() y defaultdict() de collections en un objeto, que será un dict ordenado y predeterminado. es posible?


Aquí hay otra posibilidad, inspirada en el Super () Considered Super de Raymond Hettinger , probado en Python 2.7.X y 3.4.X:

from collections import OrderedDict, defaultdict class OrderedDefaultDict(OrderedDict, defaultdict): def __init__(self, default_factory=None, *args, **kwargs): #in python3 you can omit the args to super super(OrderedDefaultDict, self).__init__(*args, **kwargs) self.default_factory = default_factory

Si consulta el MRO de la clase (también conocido como help(OrderedDefaultDict) ), verá esto:

class OrderedDefaultDict(collections.OrderedDict, collections.defaultdict) | Method resolution order: | OrderedDefaultDict | collections.OrderedDict | collections.defaultdict | __builtin__.dict | __builtin__.object

lo que significa que cuando se inicializa una instancia de OrderedDefaultDict , difiere al init de OrderedDict , pero este a su vez llamará a los métodos de defaultdict antes de llamar a __builtin__.dict , que es precisamente lo que queremos.


Aquí hay otra solución para pensar si su caso de uso es simple como el mío y no necesariamente quiere agregar la complejidad de una implementación de clase DefaultOrderedDict a su código.

from collections import OrderedDict keys = [''a'', ''b'', ''c''] items = [(key, None) for key in keys] od = OrderedDict(items)

( None es mi valor predeterminado deseado).

Tenga en cuenta que esta solución no funcionará si uno de sus requisitos es insertar dinámicamente nuevas claves con el valor predeterminado. Una compensación de simplicidad.

Actualización 13/03/17 - Me enteré de una función de conveniencia para este caso de uso. Igual que arriba, pero puede omitir los items = ... línea items = ... y simplemente:

od = OrderedDict.fromkeys(keys)

Salida:

OrderedDict([(''a'', None), (''b'', None), (''c'', None)])

Y si sus claves son caracteres individuales, puede pasar una sola cadena:

OrderedDict.fromkeys(''abc'')

Esto tiene el mismo resultado que los dos ejemplos anteriores.

También puede pasar un valor predeterminado como segundo arg a OrderedDict.fromkeys(...) .


Lo siguiente (usando una versión modificada de esta receta ) funciona para mí:

from collections import OrderedDict, Callable class DefaultOrderedDict(OrderedDict): # Source: http://.com/a/6190500/562769 def __init__(self, default_factory=None, *a, **kw): if (default_factory is not None and not isinstance(default_factory, Callable)): raise TypeError(''first argument must be callable'') OrderedDict.__init__(self, *a, **kw) self.default_factory = default_factory def __getitem__(self, key): try: return OrderedDict.__getitem__(self, key) except KeyError: return self.__missing__(key) def __missing__(self, key): if self.default_factory is None: raise KeyError(key) self[key] = value = self.default_factory() return value def __reduce__(self): if self.default_factory is None: args = tuple() else: args = self.default_factory, return type(self), args, None, None, self.items() def copy(self): return self.__copy__() def __copy__(self): return type(self)(self.default_factory, self) def __deepcopy__(self, memo): import copy return type(self)(self.default_factory, copy.deepcopy(self.items())) def __repr__(self): return ''OrderedDefaultDict(%s, %s)'' % (self.default_factory, OrderedDict.__repr__(self))


Si quieres una solución simple que no requiera una clase, puedes usar OrderedDict. setdefault ( key, default=None ) OrderedDict. setdefault ( key, default=None ) o OrderedDict. get ( key, default=None ) OrderedDict. get ( key, default=None ) . Si solo obtiene / configura desde algunos lugares, por ejemplo, en un bucle, puede establecer fácilmente el valor predeterminado.

totals = collections.OrderedDict() for i, x in some_generator(): totals[i] = totals.get(i, 0) + x

Es aún más fácil para las listas con setdefault :

agglomerate = collections.OrderedDict() for i, x in some_generator(): agglomerate.setdefault(i, []).append(x)

Pero si lo usa más de unas pocas veces, probablemente sea mejor configurar una clase, como en las otras respuestas.


Una versión más simple de la respuesta de @zeekay es:

from collections import OrderedDict class OrderedDefaultListDict(OrderedDict): #name according to default def __missing__(self, key): self[key] = value = [] #change to whatever default you want return value