78

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

4

9 に答える 9

95

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

于 2010-01-14T13:08:13.133 に答える
37

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

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

一方、一部のアプリケーションの内部にアクセスたい場合(注目すべき例は、pydocなどのドキュメントジェネレーターです)、自由にアクセスできます。Onusはプログラマーとしてあなたにあり、あなたが何をしているのかを知り、それを適切に行うのではなく、言語に基づいてあなたにそれを強制するのではありませ

于 2010-01-14T13:39:09.420 に答える
12

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

  • _single_leading_underscore:弱い「内部使用」インジケーター。たとえばfrom M import *、名前がアンダースコアで始まるオブジェクトはインポートされません。

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

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

于 2010-01-14T13:41:07.030 に答える
7

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

Pythonに飛び込む

于 2010-01-14T13:07:57.670 に答える
6

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

class Person(object):

    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()
トレースバック(最後の最後の呼び出し):
  ファイル""、1行目、
    p .__ priva()
AttributeError:'Person'オブジェクトに属性'__priva'がありません
#説明:ここでは、そのプライベートメソッドを直接フェッチできないことがわかります。
>>> p.callpriva()
私はプライベートです
#説明:ここでは、クラス内のプライベートメソッドにアクセスできます

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

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

うわー、実際にpythonが二重アンダースコアで始まる変数を取得している場合は、最初に単一のアンダースコアとクラス名を追加することで「変換」されます。

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

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

出力->

こんにちは
トレースバック(最後の最後の呼び出し):
  ファイル""、1行目、
NameError:名前'_hello'が定義されていません

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

#test2.py
from test import _hello , hello
print hello()
print _hello()

出力->

こんにちは
こんにちはプライベート

最後に:Pythonには、同等のプライバシーサポートはありませんが、最初の1つと2つのアンダースコアは、ある程度2つのレベルのプライバシーを提供します。

于 2013-12-27T05:51:38.000 に答える
3

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

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()
于 2017-02-03T19:44:43.583 に答える
2

これはちょっと長い答えですが、ここでの本当の問題の根源、つまり可視性の範囲に到達すると思います。私がこれをくぐり抜けている間、ただそこにぶら下がってください!

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

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

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

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

趣味のプログラマー(現在は引退)として、モジュールの上部に巨大なコメントブロックとして実際に書き出されたスペックドキュメントを使用して新しいモジュールを開始します。これは、ユーザーがスペックライブラリに実際に表示する部分になります。私だけなので、まだライブラリを設定していませんが、簡単に設定できます。

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

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

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

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

于 2017-02-12T02:34:17.550 に答える
-1
import inspect


class Number:
    def __init__(self, value):
        self.my_private = value

    def set_private(self, value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        f = inspect.stack()[1][3]
        if f not in ['__init__', 'set_private']:
            raise Exception("can't access private member-my_private")
        # the default behavior
        self.__dict__[my_private] = value


def main():
    n = Number(2)
    print(n.my_private)
    n.set_private(3)
    print(n.my_private)


if __name__ == '__main__': 
    main()
于 2015-10-21T13:50:46.877 に答える
-2

私はPython2.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

于 2019-05-22T19:42:54.667 に答える