tuple keys empty dictionaries create array python dictionary syntax

python - keys - ¿Cómo usar un punto "." Para acceder a los miembros del diccionario?



python empty dictionary (18)

¿Cómo puedo acceder a los miembros del diccionario de Python mediante un punto "."?

Por ejemplo, en lugar de escribir mydict[''val''] , me gustaría escribir mydict.val .

También me gustaría acceder a los dictados anidados de esta manera. Por ejemplo

mydict.mydict2.val

se referiría a

mydict = { ''mydict2'': { ''val'': ... } }


Derive de dict e implemente __getattr__ y __setattr__ .

O puedes usar Bunch que es muy similar.

No creo que sea posible hacer una clase de Dict incorporada en el monopatín.


El lenguaje en sí no es compatible con esto, pero a veces esto sigue siendo un requisito útil. Además de la receta de Bunch, también puedes escribir un pequeño método que puede acceder a un diccionario usando una cadena punteada:

def get_var(input_dict, accessor_string): """Gets data from a dictionary using a dotted accessor-string""" current_data = input_dict for chunk in accessor_string.split(''.''): current_data = current_data.get(chunk, {}) return current_data

que apoyaría algo como esto:

>> test_dict = {''thing'': {''spam'': 12, ''foo'': {''cheeze'': ''bar''}}} >> output = get_var(test_dict, ''thing.spam.foo.cheeze'') >> print output ''bar'' >>


Esta solución es un refinamiento de la ofrecida por epool para abordar el requisito de OP para acceder a los dictados anidados de manera consistente. La solución de epool no permitió el acceso a los dictados anidados.

class YAMLobj(dict): def __init__(self, args): super(YAMLobj, self).__init__(args) if isinstance(args, dict): for k, v in args.iteritems(): if not isinstance(v, dict): self[k] = v else: self.__setattr__(k, YAMLobj(v)) def __getattr__(self, attr): return self.get(attr) def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): super(YAMLobj, self).__setitem__(key, value) self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): super(YAMLobj, self).__delitem__(key) del self.__dict__[key]

Con esta clase, uno ahora puede hacer algo como: ABCD .


Instalar dotmap través de pip

pip install dotmap

Hace todo lo que quiere hacer y subclases dict , por lo que funciona como un diccionario normal:

from dotmap import DotMap m = DotMap() m.hello = ''world'' m.hello m.hello += ''!'' # m.hello and m[''hello''] now both return ''world!'' m.val = 5 m.val2 = ''Sam''

Además de eso, puedes convertirlo hacia y desde objetos dict :

d = m.toDict() m = DotMap(d) # automatic conversion in constructor

Esto significa que si algo que desea acceder ya está en formato dict , puede convertirlo en un DotMap para facilitar el acceso:

import json jsonDict = json.loads(text) data = DotMap(jsonDict) print data.location.city

Finalmente, crea automáticamente nuevas instancias de DotMap para que pueda hacer cosas como esta:

m = DotMap() m.people.steve.age = 31

Comparación con Bunch

DotMap completa: soy el creador de DotMap . Lo creé porque a Bunch le faltaban estas características

  • recordando los elementos de orden se agregan e iteran en ese orden
  • Creación automática de DotMap niños, que ahorra tiempo y DotMap un código más limpio cuando tiene mucha jerarquía
  • construir desde un dict y convertir recursivamente todas las instancias dict secundarias a DotMap

Intenté esto:

class dotdict(dict): def __getattr__(self, name): return self[name]

puedes probar __getattribute__ también.

hacer que cada dicción sea un tipo de dotdict sería lo suficientemente bueno, si quieres iniciar esto desde un dict de capas múltiples, intenta implementar __init__ también.


Me gusta Munch y ofrece muchas opciones útiles además del acceso a puntos.

importación masca

temp_1 = {''persona'': {''fname'': ''senthil'', ''lname'': ''ramalingam''}}

dict_munch = munch.munchify (temp_1)

dict_munch.person.fname


Me gustaría lanzar mi propia solución al ring:

https://github.com/skorokithakis/jsane

Le permite analizar JSON en algo a lo que puede acceder with.attribute.lookups.like.this.r() , sobre todo porque no había visto esta respuesta antes de empezar a trabajar en ella.


No es una respuesta directa a la pregunta del OP, sino inspirada y quizás útil para algunos. He creado una solución basada en objetos usando el __dict__ interno (de ningún modo código optimizado)

payload = { "name": "John", "location": { "lat": 53.12312312, "long": 43.21345112 }, "numbers": [ { "role": "home", "number": "070-12345678" }, { "role": "office", "number": "070-12345679" } ] } class Map(object): """ Dot style access to object members, access raw values with an underscore e.g. class Foo(Map): def foo(self): return self.get(''foo'') + ''bar'' obj = Foo(**{''foo'': ''foo''}) obj.foo => ''foobar'' obj._foo => ''foo'' """ def __init__(self, *args, **kwargs): for arg in args: if isinstance(arg, dict): for k, v in arg.iteritems(): self.__dict__[k] = v self.__dict__[''_'' + k] = v if kwargs: for k, v in kwargs.iteritems(): self.__dict__[k] = v self.__dict__[''_'' + k] = v def __getattribute__(self, attr): if hasattr(self, ''get_'' + attr): return object.__getattribute__(self, ''get_'' + attr)() else: return object.__getattribute__(self, attr) def get(self, key): try: return self.__dict__.get(''get_'' + key)() except (AttributeError, TypeError): return self.__dict__.get(key) def __repr__(self): return u"<{name} object>".format( name=self.__class__.__name__ ) class Number(Map): def get_role(self): return self.get(''role'') def get_number(self): return self.get(''number'') class Location(Map): def get_latitude(self): return self.get(''lat'') + 1 def get_longitude(self): return self.get(''long'') + 1 class Item(Map): def get_name(self): return self.get(''name'') + " Doe" def get_location(self): return Location(**self.get(''location'')) def get_numbers(self): return [Number(**n) for n in self.get(''numbers'')] # Tests obj = Item({''foo'': ''bar''}, **payload) assert type(obj) == Item assert obj._name == "John" assert obj.name == "John Doe" assert type(obj.location) == Location assert obj.location._lat == 53.12312312 assert obj.location._long == 43.21345112 assert obj.location.latitude == 54.12312312 assert obj.location.longitude == 44.21345112 for n in obj.numbers: assert type(n) == Number if n.role == ''home'': assert n.number == "070-12345678" if n.role == ''office'': assert n.number == "070-12345679"


No lo hagas El acceso de atributos y la indexación son cosas separadas en Python, y no debería querer que realicen lo mismo. Haga una clase (posiblemente una creada por namedtuple ) si tiene algo que debería tener atributos accesibles y use notación [] para obtener un elemento de un dict.


Para construir sobre la respuesta de epool, esta versión le permite acceder a cualquier dictado dentro del operador de punto:

foo = { "bar" : { "baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ] } }

Por ejemplo, foo.bar.baz[1].baba devuelve "loo" .

class Map(dict): def __init__(self, *args, **kwargs): super(Map, self).__init__(*args, **kwargs) for arg in args: if isinstance(arg, dict): for k, v in arg.iteritems(): if isinstance(v, dict): v = Map(v) if isinstance(v, list): self.__convert(v) self[k] = v if kwargs: for k, v in kwargs.iteritems(): if isinstance(v, dict): v = Map(v) elif isinstance(v, list): self.__convert(v) self[k] = v def __convert(self, v): for elem in xrange(0, len(v)): if isinstance(v[elem], dict): v[elem] = Map(v[elem]) elif isinstance(v[elem], list): self.__convert(v[elem]) def __getattr__(self, attr): return self.get(attr) def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): super(Map, self).__setitem__(key, value) self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): super(Map, self).__delitem__(key) del self.__dict__[key]


Puedes hacerlo usando esta clase que acabo de hacer. Con esta clase puede usar el objeto Map como otro diccionario (incluida la serialización json) o con la notación de puntos. Espero ayudarte:

class Map(dict): """ Example: m = Map({''first_name'': ''Eduardo''}, last_name=''Pool'', age=24, sports=[''Soccer'']) """ def __init__(self, *args, **kwargs): super(Map, self).__init__(*args, **kwargs) for arg in args: if isinstance(arg, dict): for k, v in arg.iteritems(): self[k] = v if kwargs: for k, v in kwargs.iteritems(): self[k] = v def __getattr__(self, attr): return self.get(attr) def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): super(Map, self).__setitem__(key, value) self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): super(Map, self).__delitem__(key) del self.__dict__[key]

Ejemplos de uso:

m = Map({''first_name'': ''Eduardo''}, last_name=''Pool'', age=24, sports=[''Soccer'']) # Add new key m.new_key = ''Hello world!'' # Or m[''new_key''] = ''Hello world!'' print m.new_key print m[''new_key''] # Update values m.new_key = ''Yay!'' # Or m[''new_key''] = ''Yay!'' # Delete key del m.new_key # Or del m[''new_key'']


Si desea recuperar su diccionario modificado, debe agregar algunos métodos de estado a las respuestas anteriores:

class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(self, attr): return self.get(attr) __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ def __getstate__(self): return self def __setstate__(self, state): self.update(state) self.__dict__ = self


Siempre he guardado esto en un archivo util. Puedes usarlo como mixin en tus propias clases también.

>>> class dotdict(dict): ... """dot.notation access to dictionary attributes""" ... __getattr__ = dict.get ... __setattr__ = dict.__setitem__ ... __delattr__ = dict.__delitem__ ... >>> mydict = {''val'':''it works''} >>> nested_dict = {''val'':''nested works too''} >>> mydict = dotdict(mydict) >>> mydict.val ''it works'' >>> mydict.nested = dotdict(nested_dict) >>> mydict.nested.val ''nested works too''


Sobre la base de la respuesta de Kugel y teniendo en cuenta las palabras de precaución de Mike Graham, ¿qué pasaría si hacemos un envoltorio?

class DictWrap(object): """ Wrap an existing dict, or create a new one, and access with either dot notation or key lookup. The attribute _data is reserved and stores the underlying dictionary. When using the += operator with create=True, the empty nested dict is replaced with the operand, effectively creating a default dictionary of mixed types. args: d({}): Existing dict to wrap, an empty dict is created by default create(True): Create an empty, nested dict instead of raising a KeyError example: >>>dw = DictWrap({''pp'':3}) >>>dw.a.b += 2 >>>dw.a.b += 2 >>>dw.a[''c''] += ''Hello'' >>>dw.a[''c''] += '' World'' >>>dw.a.d >>>print dw._data {''a'': {''c'': ''Hello World'', ''b'': 4, ''d'': {}}, ''pp'': 3} """ def __init__(self, d=None, create=True): if d is None: d = {} supr = super(DictWrap, self) supr.__setattr__(''_data'', d) supr.__setattr__(''__create'', create) def __getattr__(self, name): try: value = self._data[name] except KeyError: if not super(DictWrap, self).__getattribute__(''__create''): raise value = {} self._data[name] = value if hasattr(value, ''items''): create = super(DictWrap, self).__getattribute__(''__create'') return DictWrap(value, create) return value def __setattr__(self, name, value): self._data[name] = value def __getitem__(self, key): try: value = self._data[key] except KeyError: if not super(DictWrap, self).__getattribute__(''__create''): raise value = {} self._data[key] = value if hasattr(value, ''items''): create = super(DictWrap, self).__getattribute__(''__create'') return DictWrap(value, create) return value def __setitem__(self, key, value): self._data[key] = value def __iadd__(self, other): if self._data: raise TypeError("A Nested dict will only be replaced if it''s empty") else: return other


Terminé probando AMBAS bibliotecas AttrDict y Bunch y descubrí que eran formas de ralentizar mi uso. Después de que un amigo y yo lo investigamos, descubrimos que el método principal para escribir estas bibliotecas hace que la biblioteca repita agresivamente a través de un objeto anidado y haga copias del objeto del diccionario en todo momento. Con esto en mente, hicimos dos cambios clave. 1) Hicimos atributos con carga diferida 2) en lugar de crear copias de un objeto de diccionario, creamos copias de un objeto proxy liviano. Esta es la implementación final. El aumento en el rendimiento de usar este código es increíble. Al usar AttrDict o Bunch, estas dos bibliotecas consumieron solo 1/2 y 1/3 respectivamente de mi tiempo de solicitud (¿¡qué !?). Este código redujo ese tiempo a casi nada (en algún lugar en el rango de 0.5ms). Esto, por supuesto, depende de tus necesidades, pero si estás usando esta funcionalidad bastante en tu código, definitivamente ve con algo simple como este.

class DictProxy(object): def __init__(self, obj): self.obj = obj def __getitem__(self, key): return wrap(self.obj[key]) def __getattr__(self, key): try: return wrap(getattr(self.obj, key)) except AttributeError: try: return self[key] except KeyError: raise AttributeError(key) # you probably also want to proxy important list properties along like # items(), iteritems() and __len__ class ListProxy(object): def __init__(self, obj): self.obj = obj def __getitem__(self, key): return wrap(self.obj[key]) # you probably also want to proxy important list properties along like # __iter__ and __len__ def wrap(value): if isinstance(value, dict): return DictProxy(value) if isinstance(value, (tuple, list)): return ListProxy(value) return value

Consulte la implementación original here en https://.com/users/704327/michael-merickel .

La otra cosa a tener en cuenta, es que esta implementación es bastante simple y no implementa todos los métodos que pueda necesitar. Tendrá que escribir los que sean necesarios en los objetos DictProxy o ListProxy.


Una forma simple de obtener acceso por punto (pero no por acceso de matriz) es usar un objeto simple en Python. Me gusta esto:

class YourObject: def __init__(self, *args, **kwargs): for k, v in kwargs.items(): setattr(self, k, v)

... y usarlo así:

>>> obj = YourObject(key="value") >>> print(obj.key) "value"

... para convertirlo en un dict:

>>> print(obj.__dict__) {"key": "value"}


Fabric tiene una implementation realmente agradable y mínima. Ampliando eso para permitir el acceso anidado, podemos usar un defaultdict , y el resultado se ve así:

from collections import defaultdict class AttributeDict(defaultdict): def __init__(self): super(AttributeDict, self).__init__(AttributeDict) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(key) def __setattr__(self, key, value): self[key] = value

Haz uso de él de la siguiente manera:

keys = AttributeDict() keys.abc.xyz.x = 123 keys.abc.xyz.a.b.c = 234

Eso se desarrolla un poco en la respuesta de Kugel de "Derive from dict and and implementation __getattr__ and __setattr__ ". ¡Ahora sabes cómo!


def dict_to_object(dick): # http://.com/a/1305663/968442 class Struct: def __init__(self, **entries): self.__dict__.update(entries) return Struct(**dick)

Si uno decide convertir permanentemente esa dict en objeto, esto debería hacer. Puede crear un objeto desechable justo antes de acceder.

d = dict_to_object(d)