以下哪两种方法被认为是最佳做法?两者都取得了相同的结果。
class Foo():
LABELS = ('One','Two','Three')
class Bar():
def __init__(self):
self.__labels = ('One','Two','Three')
@property
def labels(self):
return self.__labels
答案 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,这可能是为你的常数添加结构。