Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

196
Vistas
Can I access a nested dict with a list of keys?

I would like to access a dictionary programmatically. I know how to do this with a recursive function, but is there a simpler way?

example = {'a': {'b': 'c'},
           '1': {'2': {'3': {'4': '5'}}}}

keys = ('a', 'b')
example[keys] = 'new'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': {'3': {'4': '5'}}}}


keys = ('1', '2', '3', '4')
example[keys] = 'foo'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': {'3': {'4': 'foo'}}}}


keys = ('1', '2')
example[keys] = 'bar'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': 'bar'}}
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

What you seem to want to do is define your own class of dictionary that supports this kind of indexing. We can attain a fairly neat syntax by using the fact that when you do d[1, 2, 3], Python actually passes the tuple (1, 2, 3) to __getitem__.

class NestedDict:
    def __init__(self, *args, **kwargs):
        self.dict = dict(*args, **kwargs)

    def __getitem__(self, keys):
        # Allows getting top-level branch when a single key was provided
        if not isinstance(keys, tuple):
            keys = (keys,)

        branch = self.dict
        for key in keys:
            branch = branch[key]

        # If we return a branch, and not a leaf value, we wrap it into a NestedDict
        return NestedDict(branch) if isinstance(branch, dict) else branch

    def __setitem__(self, keys, value):
        # Allows setting top-level item when a single key was provided
        if not isinstance(keys, tuple):
            keys = (keys,)

        branch = self.dict
        for key in keys[:-1]:
            if not key in branch:
                branch[key] = {}
            branch = branch[key]
        branch[keys[-1]] = value

Here are examples of usage

# Getting an item
my_dict = NestedDict({'a': {'b': 1}})
my_dict['a', 'b'] # 1

# Setting an item
my_dict = NestedDict()
my_dict[1, 2, 3] = 4
my_dict.dict # {1: {2: {3: 4}}}

# You can even get a branch
my_dict[1] # NestedDict({2: {3: 4}})
my_dict[1][2, 3] # 4

You can then make NestedDict implementation richer by also defining __iter__, __len__ and __contains__.

Also, this can be integrated fairly easily in your code since any pre-existing dictionary can be turned into a nested one by doing NestedDict(your_dict).

over 4 years ago · Santiago Trujillo Denunciar

0

This solution creates another dictionary with same keys and then updates the existing dictionary:

#!/usr/bin/env python

from six.moves import reduce


def update2(input_dictionary, new_value, loc):
    """
    Update a dictionary by defining the keys.

    Parameters
    ----------
    input_dictionary : dict
    new_value : object
    loc : iterable
        Location

    Returns
    -------
    new_dict : dict

    Examples
    --------
    >>> example = {'a': {'b': 'c'}, '1': {'2': {'3': {'4': '5'}}}}

    >>> update2(example, 'new', ('a', 'b'))
    {'a': {'b': 'new'}, '1': {'2': {'3': {'4': '5'}}}}

    >>> update2(example, 'foo', ('1', '2', '3', '4'))
    {'a': {'b': 'new'}, '1': {'2': {'3': {'4': 'foo'}}}}

    >>> update2(example, 'bar', ('1', '2'))
    {'a': {'b': 'new'}, '1': {'2': 'bar'}}
    """
    new_dict = reduce(lambda x, y: {y: x}, reversed(loc), new_value)
    input_dictionary.update(new_dict)
    return input_dictionary

if __name__ == '__main__':
    import doctest
    doctest.testmod()

use string, list or tuple for access keys

over 4 years ago · Santiago Trujillo Denunciar

0

You can use a smaller recursive function with a dictionary comprehension:

import functools
def all_examples(f):
   def wrapper():
      def update_dict(d, path, target):
         return {a:target if path[-1] == a else update_dict(b, path, target) if isinstance(b, dict) else b for a, b in d.items()}
      current_d = {'a': {'b': 'c'},'1': {'2': {'3': {'4': '5'}}}}
      final_ds = []          
      for i in f():
         current_d = update_dict(current_d, *i)
         final_ds.append(current_d)
      return final_ds
   return wrapper

@all_examples
def input_data():
  return [[('a', 'b'), 'new'], [('1', '2', '3', '4'), 'foo'], [('1', '2'), 'bar']]

for i in input_data():
  print(i)

Output:

{'a': {'b': 'new'}, '1': {'2': {'3': {'4': '5'}}}}
{'a': {'b': 'new'}, '1': {'2': {'3': {'4': 'foo'}}}}
{'a': {'b': 'new'}, '1': {'2': 'bar'}}
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda