疑わしい場合は、「公開」のままにしてください。つまり、属性の名前を隠すために何も追加しないでください。内部的な値を持つクラスがある場合は、気にしないでください。書く代わりに:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
デフォルトでこれを書きます:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
これは確かに物議を醸す方法です。Pythonの初心者はそれを嫌い、古いPythonの人もこのデフォルトを軽視しています-とにかくこれがデフォルトなので、不快に感じても、従うことをお勧めします。
どうしても「これは触れない!」というメッセージを送りたい場合 ユーザーにとって、通常の方法は、変数の前に1つの下線を付けることです。これは単なる慣例ですが、人々はそれを理解し、そのようなものを扱うときは二重の注意を払います:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use it to be relaxed about it
def push(self, value):
self._storage.append(value)
これは、プロパティ名と属性名の間の競合を回避するためにも役立ちます。
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
ダブルアンダースコアはどうですか?まあ、二重下線マジックは主にメソッドの偶発的なオーバーロードとスーパークラスの属性との名前の競合を避けるために使用されます。何度も拡張されることが予想されるクラスを作成する場合は、非常に便利です。
他の目的で使用する場合は使用できますが、通常ではなく、推奨もされていません。
編集する:なぜこれがそうなのですか?さて、通常のPythonスタイルは、物事をプライベートにすることを強調していません-逆に!それには多くの理由があります-それらのほとんどは物議を醸しています...それらのいくつかを見てみましょう。
Pythonにはプロパティがあります
今日のほとんどのオブジェクト指向言語は、反対のアプローチを使用しています。使用すべきでないものは表示されるべきではないため、属性はプライベートである必要があります。理論的には、オブジェクト内の値を無謀に変更する人はいないため、これにより、管理しやすく、結合度の低いクラスが生成されます。
しかし、それはそれほど単純ではありません。たとえば、Javaクラスは、多くの属性持っているとちょうどゲッター取得値とちょうどセッター設定値を。たとえば、単一の属性を宣言するには7行のコードが必要です。これは、Pythonプログラマーが不必要に複雑であると言うでしょう。また、実際には、ゲッターとセッターを使用してその値を変更できるため、1つのパブリックフィールドを取得するためにこのコード全体を記述するだけです。
それでは、なぜデフォルトのプライベートポリシーに従うのでしょうか。デフォルトで属性を公開するだけです。もちろん、これはJavaでは問題があります。属性に検証を追加する場合、すべてを変更する必要があるためです。
person.age = age;
あなたのコードで、私たちに言いましょう、
person.setAge(age);
setAge()
であること:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
したがって、Java(および他の言語)では、デフォルトでゲッターとセッターを使用することになります。これらは記述が面倒な場合がありますが、私が説明した状況にいる場合は、多くの時間を節約できます。
ただし、Pythonにはプロパティがあるため、Pythonでこれを行う必要はありません。このクラスがある場合:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
そして、年齢を検証することに決めた場合person.age = age
、コードの一部を変更する必要はありません。プロパティを追加するだけです(以下を参照)。
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
それを行うことができ、引き続きを使用 person.age = age
する場合、プライベートフィールドとゲッターおよびセッターを追加する理由
(また、参照PythonはJavaのではないとゲッターとセッターを使用しての害についてのこの記事。)。
とにかくすべてが表示されている-非表示にしようとすると、作業が複雑になる
プライベート属性がある言語でも、何らかのリフレクション/イントロスペクションライブラリを介してそれらにアクセスできます。そして、人々はフレームワークで、そして緊急のニーズを解決するために、それをたくさんします。問題は、イントロスペクションライブラリは、パブリック属性で実行できることを実行するための難しい方法にすぎないことです。
Pythonは非常に動的な言語であるため、この負担をクラスに追加することは逆効果です。
問題を確認することはできません- 必要です確認するがあります
Pythonistaにとって、カプセル化はクラスの内部を見ることができないことではなく、それを見ることを避ける可能性です。つまり、カプセル化とは、ユーザーが内部の詳細を気にすることなくコンポーネントを使用できるようにするコンポーネントのプロパティです。コンポーネントの実装に煩わされることなくコンポーネントを使用できる場合、そのコンポーネントは(Pythonプログラマーの意見では)カプセル化されます。
さて、実装の詳細について考えることなくクラスを使用できるようにクラスを作成した場合、必要に応じて問題はありません。何らかの理由でクラスの内部を見るために。ポイントは:あなたのAPIは良いはずで、残りは詳細です。
グイドはそう言った
まあ、これは物議を醸すものではありません:彼はそう言った、実際には。(「オープン着物」を探してください。)
これは文化です
はい、いくつかの理由がありますが、重大な理由はありません。これは主に、Pythonでのプログラミングの文化的な側面です。正直なところ、それも逆の可能性もありますが、そうではありません。また、逆に簡単に尋ねることもできます。なぜ一部の言語はデフォルトでプライベート属性を使用するのですか?Pythonの実践と同じ主な理由で、それはこれらの言語の文化であり、それぞれの選択肢には長所と短所があります。
この文化はすでにあるので、それに従うことをお勧めします。そうしないと__
、スタックオーバーフローで質問するときに、Pythonプログラマーがコードからを削除するように指示することに苛立ちます。