1

Sometimes I come across the situation that I have some data in a nested dict with rather long key-names (sometimes unavoidable for one reason or another).

some_dict = {'not_too_short_key_one': {'second_lvl_key_one': 23,
                                       'one_more_second_lvl_key': 5},
             'not_too_short_key_two': {'second_lvl_key_two': 123,
                                       'one_more_second_lvl_key': 321}}

At times I then have to pass some elements of the dict into some functions more than once:

# option 1

do_something(some_dict['not_too_short_key_one']['second_lvl_key_one'])

do_something_more(some_dict['not_too_short_key_one']['second_lvl_key_one'],
                  some_dict['not_too_short_key_one']['second_lvl_key_two'])

do_yet_another_thing(some_dict['not_too_short_key_one']['second_lvl_key_one',
                     some_dict['not_too_short_key_one']['second_lvl_key_two',
                     some_dict['not_too_short_key_two']['second_lvl_key_one'])

do_yet_another_thing(some_dict['not_too_short_key_one']['second_lvl_key_one',
                     some_dict['not_too_short_key_one']['second_lvl_key_two',
                     some_dict['not_too_short_key_two']['second_lvl_key_one'])

I wonder if introducing variables with the sole purpose to abbreviate dict entries makes sense in these situations. Would the following be encouraged? One the one hand it makes individual function calls somewhat less verbose and may significantly reduce overall code-size. On the other hand, each variable that gets introduced might change and thus makes it harder for another person to understand how the program works. Also it adds another level of indirection for a reader.

# option 2

item_1 = some_dict['not_too_short_key_one']['second_lvl_key_one']
item_2 = some_dict['not_too_short_key_one']['second_lvl_key_two']
item_3 = some_dict['not_too_short_key_two']['second_lvl_key_two']

do_something(item_1)
do_something_more(item_1, item_2)
do_yet_another_thing(item_1, item_2, item_3)
do_yet_another_thing(item_1, item_2, item_3)

Is there some sort of consensus on how to deal with this issue (e.g. prefer option 1 or option 2) or maybe some sort of naming convention for "abbreviation variables" that is generally agreed upon?

2 Answers 2

4

This is absolutely a good thing to do. Introducing intermediate variables with meaningful names simultaneously reduces reading time and adds implicit documentation.

If you're worried about the values inadvertently changing, you can make the new vars final (well, not in Python, but in principle).

In practice the advantages are even clearer than in your example because it's so abstract. Exchanging something like

configurator['hkey_local_machine'][0]['interfaces']['IP4']

with

my_ip

is a no-brainer in my view.

1

The question is: which one is more readable and easier to understand/maintain?

Duplicate code is not bad per se and your concerns about introducing variables are valid, because they increase cognitive load while reading the code (i.e. you have to keep in mind each one and pay attention if they change)

So over these two options I would prefer the first one. But I'd suggest a third:

Introduce functions instead of variables

def item_1_from_dict(dict):
    return dict['not_to_short_key_one']['second_lvl_key_one']


do_something(item_1_from_dict(some_dict))

Of course item_1_from_dict should have a meaningful name.

Advantages:

  • The "do something with the dict" code block gets more succinct
  • No temporary variables to keep track of
  • => Less temporary coupling, each line works on its own
  • No need to abbreviate names, the language is still clear and explicit
3
  • if you have a rather long dictionarry, that could make a lot of function to get what you need :x
    – Walfrat
    Dec 22, 2016 at 10:32
  • or a lot of variables, is that better? And you always can modularize Dec 22, 2016 at 10:35
  • 1
    well I do prefer lot of variable instead of lot of getter function. BUt I think I'd just alias the first level of the dictionnary.
    – Walfrat
    Dec 22, 2016 at 10:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.