My module uses constants that I feel should be grouped. Dog and cat have a number of legs and favorite foods.
I thought about:
Constants at module level:
DOG_NUMBER_OF_LEGS = 4
DOG_FAVOURITE_FOOD = ["Socks", "Meat"]
CAT_NUMBER_OF_LEGS = 4
CAT_FAVOURITE_FOOD = ["Lasagna", "Fish"]
They seem not grouped, but it is the solution 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 don't like this as they're classes I won't use but can be actually instantiated.
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 don't want to expose those internal constants. What is the most pythonic way or how would you do it?
I would go for a fourth option, preferring a collections.namedtuple
:
Animal = namedtuple('Animal', 'number_of_legs favourite_food')
You then create instances like:
DOG = Animal(4, ['Socks', 'Meat'])
CAT = Animal(4, ['Lasagna', 'Fish'])
and access the values externally as:
from animals import CAT
print CAT.number_of_legs
There's really no point having classes if you don't need to create any methods, and I think the form of access above is neater than e.g.:
from animals import animals
print animals['CAT']['number_of_legs']
namedtuple
s, like vanilla tuple
s, are immutable, too, so you can't accidentally reassign e.g. CAT.number_of_legs = 2
somewhere.
Finally, the namedtuple
is a lightweight data structure, which may be important if you're creating lots of 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