679

私は Java の世界から来て、Bruce Eckels のPython 3 Patterns, Recipes and Idiomsを読んでいます。

クラスについて読んでいると、Python ではインスタンス変数を宣言する必要がないことがわかります。コンストラクターでそれらを使用するだけで、ブームが発生します。

たとえば、次のようになります。

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

それが真の場合、クラスの任意のオブジェクトは、クラスの外部でSimple変数の値を変更できます。s

例えば:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

Java では、public/private/protected 変数について教えられてきました。クラス外の誰もアクセスできないクラス内の変数が必要な場合があるため、これらのキーワードは理にかなっています。

なぜPythonでそれが必要ないのですか?

4

13 に答える 13

1083

それは文化的です。Python では、他のクラスのインスタンスまたはクラス変数に書き込みません。Java では、本当にやりたいのであれば、同じことをすることを妨げるものは何もありません。結局のところ、いつでもクラス自体のソースを編集して、同じ効果を得ることができます。Python はそのようなセキュリティのふりをやめ、プログラマーが責任を持つことを奨励しています。実際には、これは非常にうまく機能します。

何らかの理由でプライベート変数をエミュレートしたい場合は、いつでもPEP 8__のプレフィックスを使用できます。Python は、変数の名前を次のように変更して、それらを含むクラスの外部のコードから簡単に認識されないようにします (ただし、Java の保護を回避できるのと同じように、十分に決心していれば回避できます) )。__foo

同じ慣習により、_接頭辞は、技術的に禁止されていなくても近づかないことを意味します。__fooまたはのように見える別のクラスの変数をいじってはいけません_bar

于 2009-10-29T02:01:29.063 に答える
35

上記のコメントの多くで正しく述べられているように、アクセス修飾子の主な目標を忘れないようにしましょう: コードのユーザーが変更すべきものと変更すべきでないものを理解できるようにすることです。プライベート フィールドが表示されたら、それをいじってはいけません。したがって、Python で _ と __ を使用して簡単に実現できるのは、ほとんどがシンタックス シュガーです。

于 2014-11-17T05:17:25.737 に答える
18

アンダースコア規則には、プライベート変数のバリエーションがあります。

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

微妙な違いがいくつかありますが、プログラミング パターンのイデオロギー的純粋性のためには、それで十分です。

概念をより厳密に実装する @private デコレータの例がありますが、YMMV. おそらく、メタを使用するクラス定義を書くこともできます

于 2014-09-02T01:19:15.147 に答える
11

Python では、2 つのアンダースコアで始まる識別子の前にクラス名を自動的に追加する機能により、プライベート識別子のサポートが制限されています。これはほとんどの場合、プログラマーには透過的ですが、最終的な効果は、この方法で名前が付けられた変数をプライベート変数として使用できることです。

詳細については、こちらを参照してください。

一般に、Python のオブジェクト指向の実装は、他の言語に比べて少し原始的です。しかし、私は実際にこれを楽しんでいます。これは概念的に非常に単純な実装であり、言語の動的なスタイルにうまく適合します。

于 2009-10-29T01:59:36.487 に答える
11

「Java では、public/private/protected 変数について教えられました」

「Pythonでそれが必要ないのはなぜですか?」

同じ理由で、Java では必要ありません。

privateとを使用するかどうかは自由ですprotected

Python および Java プログラマーとして、私はprivateprotectedが非常に重要な設計概念であることを発見しました。しかし、実際問題として、Java と Python の数万行の中で、実際にprivateorを使用したことはありませんprotected

なぜだめですか?

これが私の質問です「誰から保護されていますか?」

私のチームの他のプログラマー? 彼らはソースを持っています。変更できる場合、保護されているとはどういう意味ですか?

他のチームの他のプログラマー? 彼らは同じ会社で働いています。彼らは、電話で情報源を得ることができます。

クライアント?これは、(一般に)雇われのプログラミングです。クライアントは (通常) コードを所有します。

では、正確には、誰から保護しているのでしょうか?

于 2009-10-29T02:28:33.533 に答える
7

私がプライベート変数を使用するのは、変数への書き込みまたは変数からの読み取り時に他のことを行う必要がある場合だけであり、そのため、セッターおよび/またはゲッターの使用を強制する必要があります。

繰り返しますが、これはすでに述べたように文化に当てはまります。私は、他のクラス変数の読み書きが自由にできるプロジェクトに取り組んできました。1 つの実装が非推奨になると、その関数を使用するすべてのコード パスを特定するのにかなりの時間がかかりました。セッターとゲッターの使用が強制された場合、非推奨のメソッドが呼び出されたことと、それを呼び出すコード パスを識別するデバッグ ステートメントを簡単に作成できます。

誰でも拡張機能を作成できるプロジェクトに参加している場合、いくつかのリリースで消える非推奨のメソッドについてユーザーに通知することは、アップグレード時にモジュールの破損を最小限に抑えるために不可欠です。

だから私の答えは; あなたとあなたの同僚が単純なコード セットを維持している場合、クラス変数を保護することは必ずしも必要ではありません。拡張可能なシステムを作成している場合、コードを使用するすべての拡張機能でキャッチする必要があるコアへの変更が行われると、それが不可欠になります。

于 2013-04-28T17:22:44.923 に答える
5

プライベートで保護された概念は非常に重要です。しかし、python - 開発に利用できる限られたリソースを使用してプロトタイピングと迅速な開発を行うためのツールにすぎません。そのため、python では一部の保護レベルがそれほど厳密ではありません。クラスメンバーで「__」を使用できます。これは適切に機能しますが、見た目が十分ではありません。そのようなフィールドへの各アクセスには、これらの文字が含まれています。

また、python OOP の概念は完全ではなく、smaltalk や ruby​​ は純粋な OOP の概念にはるかに近いことに気付くでしょう。C# や Java でさえ近いです。

Python は非常に優れたツールです。しかし、それは単純化された OOP 言語です。構文的および概念的に単純化されています。Python の存在の主な目標は、非常に高速な方法で、高度な抽象化レベルで読みやすいコードを作成する可能性を開発者にもたらすことです。

于 2011-07-17T06:00:14.223 に答える