python 中的分组常量
Grouping constants in python
这主要是一个"good python style"问题。
我有一个模块使用了一些感觉应该分组的常量。
假设我们有狗和猫,它们每只都有几条腿和最喜欢的食物。
注意
- 除了狗和猫的那些常量之外,我们什么都不想要建模
- 未来我们很可能会有更多的动物。
- 这些常量不会在当前模块之外使用。
我想到了以下解决方案:
模块级别的常量
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']
namedtuple
s 与原版 tuple
s 一样,也是 不可变的 ,因此您不会意外地重新分配,例如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
这主要是一个"good python style"问题。
我有一个模块使用了一些感觉应该分组的常量。
假设我们有狗和猫,它们每只都有几条腿和最喜欢的食物。
注意
- 除了狗和猫的那些常量之外,我们什么都不想要建模
- 未来我们很可能会有更多的动物。
- 这些常量不会在当前模块之外使用。
我想到了以下解决方案:
模块级别的常量
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']
namedtuple
s 与原版 tuple
s 一样,也是 不可变的 ,因此您不会意外地重新分配,例如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