python 中的分组常量

Grouping constants in python

这主要是一个"good python style"问题。

我有一个模块使用了一些感觉应该分组的常量。

假设我们有狗和猫,它们每只都有几条腿和最喜欢的食物。

注意

  1. 除了狗和猫的那些常量之外,我们什么都不想要建模
  2. 未来我们很可能会有更多的动物。
  3. 这些常量不会在当前模块之外使用。

我想到了以下解决方案:


模块级别的常量

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

他们似乎没有真正分组,但我认为这是我更喜欢的解决方案。


类 作为命名空间

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

我不喜欢这个解决方案,因为我们将有 class 我们不会使用但它们可以实际实例化。


常量字典

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

我也考虑过添加子模块,但我真的不想暴露那些内部常量


最符合 pythonic 的方法是什么/你会怎么做?

我会选择字典方法,因为它感觉更易读且更有条理,但我认为这是个人喜好问题。

使用 classes 似乎也不是一个坏主意,如果你使用 class 只有静态变量和方法如 this 并且你从不实例化它们。

没有放之四海而皆准的答案,这实际上取决于您必须处理多少常量、如何使用它们、多态调度是否有意义以及月相。

现在在您的示例中,由于您有两组或更多组具有相似结构和含义的常量,我会选择 "classes as namespaces" 解决方案。

FWIW 防止 class 被实例化并不难:

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

但文档应该足够了 - 请记住,您的 "constants" 无论如何只是约定俗成的常量。

我会选择第四个选项,更喜欢 collections.namedtuple:

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

然后您创建如下实例:

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

并从外部访问值:

from animals import CAT

print CAT.number_of_legs

如果您不需要创建任何方法,那么 类 真的没有意义,我认为上面的访问形式比例如:

更整洁
from animals import animals

print animals['CAT']['number_of_legs']

namedtuples 与原版 tuples 一样,也是 不可变的 ,因此您不会意外地重新分配,例如CAT.number_of_legs = 2某处。

最后,namedtuple 是一种轻量级数据结构,如果您要创建大量动物,这可能很重要:

>>> 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