4

次の 2 つのアプローチのうち、ベスト プラクティスと見なされるのはどれですか? どちらも同じ結果になります。

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

最初のバリアントは、ラベルがクラスのすべてのインスタンスで宣言されていることを伝えます...

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

一方、2 番目のラベルはインスタンスごとに特別なように見えます。ラベルが一定である場合は、最初のものを使用します-より一貫性があります。

于 2013-06-21T19:26:05.420 に答える
1

PEP 8 Style Guide for Python Codeは 3 番目の方法を提供しており、Zen of 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 に答える
0

これは、変数の使用範囲によって異なります。私はクラス変数を定数への参照として使用します。これは C と同様#define SOMETHINGです。一方、インスタンス変数はインスタンスごとに異なる値を持つ場合があります。おそらく、例がこれをよりよく説明します。

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

t = ChessBoardTile(ChessBoardTile.BLACK)
于 2013-06-21T19:28:30.623 に答える
0

次の理由から、間違いなく最初のものです。

  • よりシンプルで、意図をよりよく伝えます

  • 一度だけ評価されるクラス変数であるため、使用するメモリが少なくて済みます。一方、2 番目の例では同じタプルが何度も作成され、キャッシュ (内部化) されない可能性があります。

  • 他の人が指摘したように、定数に構造を追加するための Foo.LABELS を要求できます。

于 2013-06-21T19:54:16.473 に答える
0

2 番目のアプローチを取るように説得するために例を作成しましたが、混乱しました...

>>> 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

したがって、私の元の答えに戻ります。変数が再割り当てされても気にしない限り、最初のアプローチをとらないでください。最初のアプローチは変数をクラスに所属させ、2 番目のアプローチは変数をインスタンスに所属させます。しかし、誰かが最初の状況で変数を再割り当てすると、非常に奇妙な結果が得られます。

当然の結果 - クラスメソッドがクラスの変数 (つまりFoo.LABELS) のみを参照する場合、明らかに期待どおりの結果が得られますが、誰かがあなたのコードを別の方法で再利用した場合、誰が何を得るかわかりません。

当然の結果 #2 - Python には、参照の不変性を強制する方法はありません。したがって、実際には2番目のアプローチを使用する必要があります。

于 2013-06-21T19:47:06.620 に答える