Grouping constants in python

This is basically a matter of "good python style."

I have a module that uses several constants, which, in his opinion, should be grouped.

Suppose we have Dogs and a cat, and each of them has a number of legs and a favorite food.

note that

  • we want to model nothing but constants about dogs and cats
  • Most likely, in the future we will have more animals.
  • these constants will not be used outside the current module.

I thought of the following solutions:


Module Level Constants

DOG_NUMBER_OF_LEGS = 4 DOG_FAVOURITE_FOOD = ["Socks", "Meat"] CAT_NUMBER_OF_LEGS = 4 CAT_FAVOURITE_FOOD = ["Lasagna", "Fish"] 

They don't seem to be grouped, but I think this is the solution that I prefer.


Classes as Namespaces

 class Dog(object): NUMBER_OF_LEGS = 4 DOG_FAVOURITE_FOOD = ["Socks", "Meat"] class Cat(object): NUMBER_OF_LEGS = 4 FAVOURITE_FOOD = ["Lasagna", "Fish"] 

I do not like this solution, because we will have a class that we will not use, and they can actually be created.


Dictionary of constants

 ANIMALS_CONFIG = { "DOG" : { "NUMBER_OF_LEGS" : 4, "FAVOURITE_FOOD" : ["Socks", "Meat"] }, "CAT" : { "NUMBER_OF_LEGS" : 4, "FAVOURITE_FOOD" : ["Lasagna", "Fish"] } } 

I also thought about adding submodules, but I really don't want to reveal these internal constants


What is the most pythonic way to do this / how would you do it?

+6
source share
3 answers

I would choose the fourth option, preferring collections.namedtuple :

 Animal = namedtuple('Animal', 'number_of_legs favourite_food') 

Then you create instances such as:

 DOG = Animal(4, ['Socks', 'Meat']) CAT = Animal(4, ['Lasagna', 'Fish']) 

and access the values ​​from outside like:

 from animals import CAT print CAT.number_of_legs 

Actually, it makes no sense to have classes if you don’t need to create any methods, and I think the access form above is more accurate than, for example:

 from animals import animals print animals['CAT']['number_of_legs'] 

namedtuple s, such as vanilla tuple s, are also immutable, so you cannot accidentally reassign, for example. CAT.number_of_legs = 2 somewhere.

Finally, namedtuple is a lightweight data structure that can be important if you create many animals:

 >>> import sys >>> sys.getsizeof({'number_of_legs': 4, 'favourite_food': ['Lasagna', 'Fish']}) 140 >>> from collections import namedtuple >>> Animal = namedtuple('Animal', 'number_of_legs favourite_food') >>> sys.getsizeof(Animal(4, ['Lasagna', 'Fish'])) 36 
+6
source

There is no answer for one size, it depends on how many constants you need to process, how you use them, if it makes sense to send polymorphism or not, and the phase of the moon.

Now in your example, since you have two or more sets of constants with a similar structure and value, I would choose the solution “classes as namespaces”.

FWIW, which impedes class creation acceleration, is not so difficult:

 >>> class Foo(object): ... def __new__(cls): ... return cls ... >>> Foo() <class '__main__.Foo'> 

But the documentation should be enough - remember that your "constants" in any case are constants by agreement.

+4
source

I would use the dictionary because it feels more readable and more organized, but I think this is a matter of personal preference.

Using classes also doesn't seem like a bad idea if you use a class with only static variables and methods like this , and you never create them.

+1
source

Source: https://habr.com/ru/post/985663/


All Articles