4

以下两种方法中的哪一种被认为是最佳实践?两者都达到相同的结果。

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

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

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

6 回答 6

5

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

此外,它们的行为并不完全相同。在Foo中,标签有一个类级别的属性。中Bar,没有。引用Foo.LABELS会正常工作,引用Bar.labels会抛出异常。

于 2013-06-21T19:24:56.813 回答
1

Python 代码的PEP 8 样式指南提供了第三种方式,Python 之禅对此表示赞同。

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

例如的全部内容package/constants.py

LABELS = ('One', 'Two', 'Three')

示例用法:

from package.constants import LABELS
print(LABELS)  # -> ('One', 'Two', 'Three')

请注意,这里没有任何明确的常量“保护”。您可以跳过箍以尝试获得恒定的常数...或者您可以接受您设置的任何保护措施都可能被真正想要的人绕过,然后只需重新引用有关同意成年人的内容的人,然后遵循一个非常明智的概念,即足够多的开发人员适当地尊重变量ALL_CAPS,你不应该担心强制执行你的常量概念。

于 2014-06-05T20:43:19.473 回答
1

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

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

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

于 2013-06-21T19:26:05.420 回答
0

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.

于 2013-06-21T19:54:16.473 回答
0

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

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

t = ChessBoardTile(ChessBoardTile.BLACK)
于 2013-06-21T19:28:30.623 回答
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 中没有办法强制引用不变性。所以你真的应该采用第二种方法。

于 2013-06-21T19:47:06.620 回答