Python:我应该使用常量还是属性?

时间:2013-06-21 19:21:40

标签: python syntax constants

以下哪两种方法被认为是最佳做法?两者都取得了相同的结果。

class Foo():
    LABELS = ('One','Two','Three')

class Bar():
    def __init__(self):
        self.__labels = ('One','Two','Three')

    @property
    def labels(self):
        return self.__labels

6 个答案:

答案 0 :(得分:4)

如果您不需要自定义获取或设置行为,那么制作某个属性是没有意义的。第一个版本更好。

此外,这些行为并不完全相同。在Foo中,标签有一个类级别属性。在Bar,没有。引用Foo.LABELS将正常工作,引用Bar.labels将引发异常。

答案 1 :(得分:1)

第一个变体传达,标签在所有实例类上声明,...

class Foo():
    LABELS = ('One','Two','Three')

而第二个看起来像标签是特殊的,每个实例。如果标签不变,我会选择第一个 - 它更连贯。

答案 2 :(得分:1)

PEP 8 Style Guide for Python Code提供第三种方式,Zen of Python同意。

他们建议添加一个非常简单的模块,创建一个命名空间来定义常量。

# entire of contents of e.g. /package/constants.py
LABELS=('One', 'Two', 'Three')

# example usage
from package.constants import LABELS
print('The labels are {0}'.format(LABELS))

# output
>>> The labels are ('One', 'Two', 'Three')

请注意,没有明确的常量"保护"这里。你可以通过箍来试图获得恒定的常数......或者你可以接受任何你真正想要的保护措施,然后只需重新引用任何关于同意成人和我认为ALL_CAPS中的变量得到了足够的开发人员的充分尊重,你不应该担心强制执行你的常量概念。

答案 3 :(得分:0)

这取决于变量使用的范围。我使用类变量作为常量的引用,非常类似于C中的#define SOMETHING。另一方面,实例变量可能对不同的实例具有不同的值。也许一个例子可以更好地解释这一点。

class ChessBoardTile:
    BLACK = 'black'
    WHITE = 'white'
    def __init__(self,clr):
        self._color = clr

t = ChessBoardTile(ChessBoardTile.BLACK)

答案 4 :(得分:0)

我举了一个例子,试图说服你采取第二种方法,但我感到困惑......

>>> class Foo():
...     LABELS = ('One','Two','Three')
... 
>>> Foo.LABELS
('One', 'Two', 'Three')
>>> Foo.LABELS = (1,2,3)
>>> Foo.LABELS
(1, 2, 3)
>>> f = Foo()
>>> g = Foo()
>>> f.LABELS = ('a','b','c')
>>> g.LABELS
(1, 2, 3)
>>> Foo.LABELS
(1, 2, 3)
>>> f.LABELS
('a', 'b', 'c')

“发生什么事了?”我心想。然后我意识到行为取决于对象ID ......

>>> id(Foo.LABELS)
4562309280
>>> id(g.LABELS)
4562309280
>>> id(f.LABELS)
4562068336
>>> ('a','b','c') is ('a','b','c')
False
>>> Foo.LABELS = (4,5,6)
>>> g.LABELS
(4, 5, 6)
>>> f.LABELS
('a', 'b', 'c')
>>> id(Foo.LABELS)
4562309200
>>> id(g.LABELS)
4562309200
>>> id(f.LABELS)
4562068336

所以,回到我原来的答案:不要采取第一种方法,除非你不关心你的变量是否被重新分配,因为你得到的不是你所期望的。第一种方法使变量属于类,第二种方法使变量属于实例 - 但如果有人在第一种情况下重新分配变量,则会得到一些非常奇怪的结果。

推论 - 如果你的类方法只引用类'变量(即Foo.LABELS)那么你显然会得到你所期望的,但如果有人以不同的方式重新使用你的代码,那么谁知道他们会得到什么?

推论#2 - python中没有办法强制引用不变性。所以你真的应该采用第二种方法。

答案 5 :(得分:0)

绝对是第一个,因为:

  • 它更简单,更好地传达您的意图

  • 它可能会使用更少的内存,因为它只被评估一次类变量。而第二个示例反复创建相同的元组,而它可能不会被缓存(内化)。

  • 正如其他人所指出的那样,你可以要求Foo.LABELS,这可能是为你的常数添加结构。