web-dev-qa-db-ja.com

Pythonのプライベートメンバー

Pythonでメソッドとデータメンバーをプライベートにするにはどうすればよいですか?またはPythonプライベートメンバーをサポートしていませんか?

61
appusajeev

9.6。プライベート変数

オブジェクトの内部からしかアクセスできない「プライベート」インスタンス変数は、Pythonには存在しません。ただし、ほとんどのPythonコード:アンダースコアで始まる名前(_spamなど)は、APIの非公開部分として扱われる必要があります。関数、メソッド、またはデータメンバー)実装の詳細と見なされ、予告なく変更される場合があります。

クラスプライベートメンバには有効なユースケースがあるため(つまり、サブクラスで定義された名前と名前の衝突を避けるため)、名前マングリングと呼ばれるこのようなメカニズムのサポートは制限されています。 __spam(少なくとも2つの先行アンダースコア、最大で1つの後続アンダースコア)の形式の識別子は、テキストで_classname__spamに置き換えられます。classnameは、先行アンダースコアを削除した現在のクラス名です。このマングリングは、クラスの定義内で発生する限り、識別子の構文上の位置に関係なく行われます。

したがって、 たとえば

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

出力されます:

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbolはプライベートメソッドと見なされる必要がありますが、_Test__private_symbolを介してアクセスできます。

75
jbochi

他の回答は技術的な詳細を提供します。 PythonとC++/Javaのような言語(あなたの質問に基づいてあなたはよく知っていると思います)の哲学の違いを強調したいと思います。

Python(およびその点についてはPerl)の一般的な態度は、属性の「プライバシー」はコンパイラ/インタープリターによる有刺鉄線ではなくプログラマーへの要求であるということです。 このメール にまとめられており、プログラマーが内部に干渉しないように十分に責任があると「想定している」ため、「私たちはすべて同意している大人」と呼ばれます。属性が内部的であることを示す丁寧なメッセージ。

一方、doいくつかのアプリケーションの内部にアクセスしたい場合(注目すべき例はpydocのようなドキュメントジェネレーターです)、自由にそうする。 Onusはプログラマーとしてあなたに何をしているのかを理解し、物事を強制する言語ではなく適切にそれを行うことですit's方法。

34
Noufal Ibrahim

Pythonには他のアクセス保護メカニズムのprivateはありません。クラスのユーザーに特定の属性にアクセスしてはならないことを示すために、 Pythonスタイルガイド に文書化された規則があります。

  • _single_leading_underscore:弱い「内部使用」インジケータ。例えば。 from M import *は、名前が下線で始まるオブジェクトをインポートしません。

  • single_trailing_underscore_:Pythonキーワード、たとえばTkinter.Toplevel(master, class_='ClassName')との競合を避けるために慣例により使用されます

  • __double_leading_underscore:クラス属性に名前を付けるとき、名前マングリングを呼び出します(クラスFooBar内では、__ booは_FooBar__booになります。以下を参照)。

6
Tendayi Mawushe

Python関数、クラスメソッド、または属性の名前が2つのアンダースコアで始まる(ただし終了しない)場合、それはプライベートです;その他はすべてパブリックです。Pythonには、保護されたクラスメソッドの概念はありません(独自のクラスおよび子孫クラスでのみアクセス可能)。クラスメソッドはプライベート(独自のクラス)またはパブリック(どこからでもアクセス可能)。

Pythonに飛び込む

6

Pythonはプライバシーを直接サポートしていません。プログラマーは、外部から属性を変更することが安全である場合を知る必要がありますが、とにかくpythonを使用すると、ちょっとしたトリックでプライベートのようなものを実現できます。

 class Person(オブジェクト):
 
 def __priva(self):
 print "I am Private" 
 
 def publ (self):
 print "I am public" 
 
 def callpriva(self):
 self .__ priva()

さて、実行するとき:

 >>> p = Person()
 >>> p.publ()
私はパブリックです
 >>> p .__ priva()
トレースバック(最後の最後の呼び出し):
 File ""、1行目、
 p .__ priva()
 AttributeError: 'Person' object has no attribute '__priva' 
#説明:ここで、プライベートメソッドを直接フェッチできないことがわかります。
 >>> p.callpriva()
 I am Private 
 #説明:ここで、クラス内のprivateメソッドにアクセスできます

次に、誰かがその変数にアクセスする方法???
次のようにできます:

 >>> p._Person__priva 
私はプライベートです

ワウ、実際にpythonが二重アンダースコアで始まる変数を取得している場合、単一のアンダースコアとクラス名を先頭に追加することにより「翻訳」されます:

注:この名前を変更したくないが、他のオブジェクトに信号を送信したくない場合は、スター付きでインポートされない最初のアンダースコアを持つ単一の初期アンダースコア名を使用できますインポート(モジュールインポートから*)
例:

#test.py 
 def hello():
 print "hello" 
 def _hello():
 print "Hello private" 
 
#---------------------- 
#test2.py 
テストインポートから* 
 print hello()
 print _hello()

出力->

 hello 
トレースバック(最新のコールラスト):
 File ""、1行目、
 NameError:name '_hello' is not defined 

_helloを手動で呼び出す場合。

#test2.py 
テストインポート_helloから、hello 
 print hello()
 print _hello()

出力->

 hello 
 hello private 

最後に:Pythonには同等のプライバシーサポートがありませんが、シングルとダブルの最初のアンダースコアはある程度あなたに2つのレベルのプライバシーを与えます

5
Prashant Gaur

これはうまくいくかもしれません:

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()
2
Laszlo

これはちょっとした答えですが、ここで本当の問題の根源である可視性の範囲に到達すると思います。私がこれをやり遂げている間、ただそこにいるだけです!

モジュールをインポートするだけでは、必ずしもアプリケーション開発者がそのすべてのクラスまたはメソッドにアクセスできる必要はありません。モジュールのソースコードを実際に見ることができない場合、利用可能なものをどのように知ることができますか?誰か(またはあるもの)が私にできることを教えて、使用が許可されている機能の使用方法を説明する必要があります。そうでなければ、すべては役に立たないです。

インポートされたモジュールを介して基本的なクラスとメソッドに基づいて高レベルの抽象化を開発するものには、実際のソースコードではなく、仕様書が提示されます。

モジュール仕様には、クライアント開発者に表示されることを目的としたすべての機能が記載されています。大規模なプロジェクトやソフトウェアプロジェクトチームを扱う場合、モジュールの実際の実装は、常にそれを使用するものから隠されたままにしておく必要があります。これは、外の世界へのインターフェイスを備えたブラックボックスです。 OODの純粋主義者にとって、技術用語は「分離」と「一貫性」であると信じています。モジュールのユーザーは、実装の詳細に煩わされることなく、インターフェイスメソッドを知るだけで済みます。

モジュールは、基礎となる仕様ドキュメントを最初に変更せずに変更しないでください。一部の組織では、コードを変更する前にレビュー/承認が必要になる場合があります。

趣味のプログラマー(現在は退職)として、モジュールの最上部に巨大なコメントブロックとして実際に書き出された仕様ドキュメントを使用して新しいモジュールを開始します。これは、ユーザーが実際に仕様ライブラリで見る部分です。それは私だけなので、私はまだライブラリをセットアップしていませんが、それはするのに十分簡単でしょう。

それから、さまざまなクラスとメソッドを書くことからコーディングを開始しますが、関数本体はありません( "print()"のようなnull printステートメントだけです)。この手順が完了したら、完成したnullモジュールをコンパイルします。これが私の仕様です。私がプロジェクトチームで作業している場合、ボディの肉付けを進める前に、この仕様/インターフェースをレビューと解説のために提示します。

各メソッドの本体を一度に1つずつ具体化してコンパイルし、構文エラーがその場ですぐに修正されるようにします。これは、コーディング中に各メソッドをテストするために、下部の一時的な「メイン」実行セクションの作成を開始する良い機会でもあります。コーディング/テストが完了すると、更新が必要になった場合に再度必要になるまで、すべてのテストコードがコメント化されます。

実際の開発チームでは、仕様コメントブロックもドキュメントコントロールライブラリに表示されますが、それは別の話です。要点は、モジュールクライアントとして、ソースコードではなく、この仕様のみを参照することです。

PS:開始のずっと前に、私は防衛航空宇宙コミュニティで働き、かなりクールなことをしましたが、独自のアルゴリズムや機密システムの制御ロジックなどは、非常に安全なソフトウェアライブラリで厳しく保管され、暗号化されていました。モジュール/パッケージインターフェイスにはアクセスできましたが、ブラックボックス実装本体にはアクセスできませんでした。すべてのシステムレベルの設計、ソフトウェア仕様、ソースコード、テストレコードを処理するドキュメント管理ツールがありました。すべて同期されていました。政府には、ソフトウェア品質保証基準の厳しい要件がありました。 「Ada」という言語を覚えている人はいますか?それは私が何歳です!

2
We_Are_Borg

Python 2.7および3.5を使用します。このコードを作成しました。

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

それを実行して得た:

AttributeError: 'MyOBject'オブジェクトには属性 '__private_field'がありません

参照してください: https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

0
CrazySynthax