Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are Python best practices for dictionary dict key constants?

Tags:

When using dictionary (dict) keys in Python, there seem to be a few general approaches:

  1. some_dict['key_name'] # string constants everywhere

  2. some_dict[KeyConstants.key_name] # where class KeyConstants: key_name: 'key_name'

  3. some_dict[KEY_NAME] # with from some_module import KEY_NAME # a module level constant

    1. 'key_name' has the disadvantage that you're repeating constants throughout your code. It's not DRY. Worse, if you ever go to publish an your API (in the broadest sense) you'll have consumers of your API repeating these constants everywhere, and if you ever want to change 'key_name' to 'better_key_name' it will be a breaking change.

    2. This is the typed language, DRY approach, with constants consolidated in one place. Its only disadvantages are that it's ugly, a bit less readable, and more verbose. Pythonic principles primarily prohibit that. It lets you easily change the constant representing the key, since everyone's coding against the variable KeyConstants.key_name. It also works well with IDEs for refactoring.

    3. Module level constants are recommended in the PEP 8 style guide. ALL_CAPS_ARE_LOUD and harder to type. This has some of the advantages of both options 1 and 2.

What are some other best practices for dict key constants? Which of the above approaches are preferred and when?

like image 516
velshin Avatar asked May 22 '11 14:05

velshin


People also ask

Should I use dict () or {}?

With CPython 2.7, using dict() to create dictionaries takes up to 6 times longer and involves more memory allocation operations than the literal syntax. Use {} to create dictionaries, especially if you are pre-populating them, unless the literal syntax does not work for your case.

What are two ways you can safely look up a key in a dictionary Python?

Using the Inbuilt method keys() Using if and in. Using has_key() method.

What are the constraints on acceptable data types for keys and values in dictionaries?

However, there are a couple restrictions that dictionary keys must abide by. First, a given key can appear in a dictionary only once. Duplicate keys are not allowed. A dictionary maps each key to a corresponding value, so it doesn't make sense to map a particular key more than once.


1 Answers

  1. d['key_name']
  2. d[Keys.key_name]
  3. d[KEY_NAME]

I don't really view #3 as requiring module-level imports; they just can be in the module namepsace, e.g. you could do something like How to programmatically set a global (module) variable?

The advantage of #2 over #1 is that typos and obsolete values will throw an attribute error "this key doesn't exist!" rather than an index error "could not be found!" -- which is always better. #2>#1. It's not more verbose either, because you just set K=Keys (or something) if you're typing a lot, so you have d[K.key_name], just two characters more (). For example, depending how before I'm feeling, I may do either:

import subprocess as proc proc.Popen(..., stdout=proc.PIPE) 

or

import subprocess as proc PIPE = proc.PIPE proc.Popen(..., stdout=PIPE) 

or

from subprocess import * Popen(..., stdout=PIPE) 

With regards to #3, ALL_CAPS_ARE_LOUD for a reason; it becomes confusing to distinguish between d[someVariable] (which can be holding any keyword) and d[magicKeyword] -- whereas d[MAGIC_KEYWORD] is unambiguous that it is a constant, and not some variable which may be holding a constant, e.g. for someVariable in magicKeywords. #3 basically is equivalent to #2, e.g. re.DOTALL (the re being equivalent to KeyConstants, without having to remember the name of the KeyConstants containers because it is the module). Thus #3 is superior to #2 unless you are in a strange situation where you have different types of keyspaces.

DRY / OAOO is very very important, but ultimately is not relevant to any of these, because you always need to repeat a variable name in order to refer to it; the best you can do is create an alias.

You could also consider #4, which is to endow your dictionary with attributes, e.g. d.key_name -- this is only appropriate if it's some subscriptable object.

But to quote a comment by Jochen Ritzel: "Using constant keys should be a very rare occasion" (use attributes of an object, or as he suggests perhaps a named tuple, though I've always found them to be unwieldy)

like image 63
ninjagecko Avatar answered Sep 28 '22 04:09

ninjagecko