以下两种方法中的哪一种被认为是最佳实践?两者都达到相同的结果。
class Foo():
LABELS = ('One','Two','Three')
class Bar():
def __init__(self):
self.__labels = ('One','Two','Three')
@property
def labels(self):
return self.__labels
如果您不需要自定义获取或设置行为,那么将某些东西设为属性是没有意义的。第一个版本更好。
此外,它们的行为并不完全相同。在Foo
中,标签有一个类级别的属性。中Bar
,没有。引用Foo.LABELS
会正常工作,引用Bar.labels
会抛出异常。
Python 代码的PEP 8 样式指南提供了第三种方式,Python 之禅对此表示赞同。
他们建议添加一个非常简单的模块,该模块创建一个命名空间来定义常量。
例如的全部内容package/constants.py
:
LABELS = ('One', 'Two', 'Three')
示例用法:
from package.constants import LABELS
print(LABELS) # -> ('One', 'Two', 'Three')
请注意,这里没有任何明确的常量“保护”。您可以跳过箍以尝试获得恒定的常数...或者您可以接受您设置的任何保护措施都可能被真正想要的人绕过,然后只需重新引用有关同意成年人的内容的人,然后遵循一个非常明智的概念,即足够多的开发人员适当地尊重变量ALL_CAPS
,你不应该担心强制执行你的常量概念。
第一个变体传达,标签在类的所有实例上声明,......
class Foo():
LABELS = ('One','Two','Three')
而第二个看起来标签是特殊的,例如。如果标签是不变的,我会选择第一个 - 它更加连贯。
Definitely the first one, because:
it is simpler and communicates your intent better
it may use less memory as it is class variable evaluated only once. Whereas the second example creates the same tuple over-and-over and it might not get cached (internalized).
and as others have pointed out, you could ask for Foo.LABELS which might be for adding structure to your constants.
这取决于变量使用的范围。我使用类变量作为对常量的引用,就像#define SOMETHING
在 C 中一样。另一方面,实例变量对于不同的实例可能具有不同的值。也许一个例子可以更好地解释这一点。
class ChessBoardTile:
BLACK = 'black'
WHITE = 'white'
def __init__(self,clr):
self._color = clr
t = ChessBoardTile(ChessBoardTile.BLACK)
我举了一个例子试图说服你采取第二种方法,但我很困惑......
>>> 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 中没有办法强制引用不变性。所以你真的应该采用第二种方法。