1

After Python 3.7, dictionaries are order-preserving. This allows us to get values as follows:

a = list(dict.values())[idx]

What I want to do is to set a value, which is nested as follows. There is an outer dictionary, its first value is an instance of a class. This class has another dictionary as attribute, and I would like to change the first value in this dictionary.

a = list(list(outer_dict.values())[0].dict_as_attribute.values())[0]
a = 1

How do I put the new a back to its place? The above expression gives me a copy, and when I change a, the one in the dictionary stays the same. Ofcourse, the following also doesn't work:

list(list(outer_dict.values())[0].attribute.values())[0] = a

Solutions using known keys or using different data structures don't help: I am not allowed to change the data structure and I also do not know the keys.

Thanks for the answers.

  • 1
    I don't understand the utility in this at all, why not just use a list? – roganjosh Jun 21 '22 at 17:54
  • 1
    Just because you can't change the underlying dict, it doesn't mean that you can't use a list to maintain the keys once you've called `.keys()` then do the bookkeeping on that object. Nobody would ever write code like this. – roganjosh Jun 21 '22 at 18:00
  • Sorry, I should have provided some more context: I have a few large neural networks with modules that are themselves neural networks. The modules are saved within a dictionary. There are many if-else statements which make use of the keys elsewhere in the project. So I cannot switch to a list there. I am experimenting with transfer learning, so I need to apply changes to some layers in the state_dict of the first module. Since the aim is to make some quick experiments, I do not want to undertake a large-scale change in the project. – Kağan Aytekin Jun 21 '22 at 18:25

3 Answers3

2

You can get the keys in the same way as you get the values:

outer_key = list(outer_dict.keys())[0]
inner_key = list(list(outer_dict.values())[0].attribute.keys())[0]
outer_dict[outer_key].attribute[inner_key] = a
Anonymous12358
  • 436
  • 1
  • 10
2
outer_key = next(iter(outer_dict.keys()))
inner_key = next(iter(outer_dict[outer_key].dict_as_attribute.keys()))
outer_dict[outer_key].dict_as_attribute[inner_key] = a

This avoids creating lists containing all the keys, so is more efficient.

Ian
  • 119
  • 1
  • 6
1

You need to keep a reference to the dict key, you want to change:

# dummy class
class A:
    def __init__(self):
        self.dict_as_attribute = {
            'foo': 'FOO',
            'bar': 'BAR',
            'baz': 'BAZ'
        }


outer_dict = {
    chr(k): A() for k in range(80, 85)
}


outerIndexToChange = 3
innerIndexToChange = 2
newValue = 'FOOBAR'

# change dict value
outerReference = outer_dict[list(outer_dict.keys())[outerIndexToChange]].dict_as_attribute
outerReference[list(outerReference.keys())[innerIndexToChange]] = newValue


# verify
for v in outer_dict.values():
    print(v.dict_as_attribute)

Out:

{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'FOOBAR'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47