[解決済み] Pythonの名前のマングリング
質問
他の言語では、より良いコードを生成するための一般的なガイドラインとして、常に可能な限りすべてを隠すようにすることが挙げられます。もし変数がprivateかprotectedか迷ったら、privateにするのがよいでしょう。
同じことがPythonにも当てはまりますか?最初はすべてのものに2つの先行するアンダースコアを使用し、必要なときだけそれらをより隠さなくする (1つのアンダースコアのみ) べきでしょうか?
もし慣習として1つのアンダースコアだけを使うのであれば、その根拠も知りたいです。
以下は、私が JBernardoの回答 . 私がなぜこの質問をしたのか、また、なぜPythonが他の言語と違うのかを知りたいのかが説明されています。
私は、すべてのものは必要なものだけ公開され、それ以上は公開されるべきではないと考えるように訓練された言語から来ました。その理由は、そうすることで依存関係を減らし、コードをより安全に変更できるようになるからです。公開から始まって隠蔽に向かうという、物事を逆に行うPythonのやり方は、私には奇妙です。
どのように解決するのですか?
迷ったら、"public" のままにする - つまり、属性名をわかりにくくするようなものを追加しないことです。もし、何らかの内部値を持つクラスがあるのなら、それを気にする必要はありません。書くかわりに
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
ダブルアンダースコアについてはどうでしょうか?ダブルアンダースコアの魔法を使うのは主に メソッドを誤ってオーバーロードしてしまったり、スーパークラスの属性と名前が衝突してしまったりするのを避けるためです。 . 何度も拡張されるようなクラスを書く場合、これはかなり貴重なものになります。
他の目的で使用したい場合は可能ですが、通常でも推奨でもありません。
EDIT : なぜそうなのでしょうか?通常のPythonのスタイルは、物事を非公開にすることを重視していません - その逆です! その理由はたくさんあるのですが、そのほとんどは議論を呼ぶものです...。そのうちのいくつかを見てみましょう。
Pythonにはプロパティがある
今日、ほとんどのOO言語では、反対のアプローチを採用しています。理論的には、誰もオブジェクトの値を無闇に変更しないので、これはより管理しやすく、結合の少ないクラスをもたらすでしょう。
しかし、そう単純ではありません。例えば、Javaのクラスは多くのゲッターを持ちますが、そのゲッターには を取得します。 という値を と のみのセッターです。 を設定します。 を設定するだけです。一つの属性を宣言するために、例えば7行のコードが必要です。Pythonのプログラマーなら、これは不必要に複雑だと言うでしょう。また、実際にはゲッターとセッターを使ってその値を変更できるため、1つのパブリックフィールドを取得するために多くのコードを書くことになります。
では、なぜこのprivate-by-defaultのポリシーに従うのでしょうか?属性をデフォルトでpublicにすればいいのです。もちろん、これは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が優れていることであり、あとは細部です。
Guidoはそう言いました
まあ、これは議論の余地がない。 彼はそう言った、実際に . ("open kimono."で検索してください)
これが文化だ
はい、いくつかの理由はありますが、決定的な理由はありません。これは主にPythonでプログラミングする際の文化的な側面です。率直に言って、それは他の方法でもあり得ます - しかし、そうではありません。また、逆に聞くこともできます。ある言語ではなぜデフォルトでprivate属性を使うのでしょうか?それはこれらの言語の文化であり、それぞれの選択には利点と欠点があるからです。
すでにこの文化があるのですから、それに従うのが得策です。さもなければ、Pythonのプログラマーに
__
を削除するよう指示されることになります。)
関連
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] オブジェクト名の前のシングルアンダーコアとダブルアンダーコアの意味は何ですか?
-
[解決済み] Pythonにはクラス内に「プライベート」変数がある?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonの「private」メソッドは、なぜ実際にはprivateではないのですか?
-
[解決済み】プロパティ名やメソッド名のアンダースコア接頭辞は単なる慣例?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
PicgoのイメージベッドツールをPythonで実装する
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
Python入門 openを使ったファイルの読み書きの方法
-
[解決済み】TypeError: unhashable type: 'numpy.ndarray'.
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】 AttributeError: モジュール 'matplotlib' には属性 'plot' がない。
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み】Pythonの「private」メソッドは、なぜ実際にはprivateではないのですか?