下線と下線の違い

4435 ワード

主に4つのネーミングが存在します
1. object #     
2. __object__ #     ,        
3. __object #    ,   
4. _object #    

コアスタイル:アンダースコアを変数名の先頭にしないでください.
下線は解釈器に特別な意味を持ち、組み込み識別子で使用される記号であるため、プログラマは変数名の開始として下線を使用しないことをお勧めします.一般に、変数名_objectは「プライベート」とみなされ、モジュールやクラス外では使用できず、「from module import*」でインポートできません.変数がプライベートの場合、_objectは変数を表すのに良い習慣です.
下線+クラス名、eg:_Class__objectメカニズムでアクセス可能__object__です.変数名__object__Pythonには特別な意味があるので、通常の変数ではこのネーミングスタイルは避けるべきです.
「単一下線」で始まるメンバー変数を保護変数と呼びます.これは、クラスオブジェクトとサブクラスオブジェクトだけがこれらの変数にアクセスできることを意味します.二重下線」は、クラスオブジェクトのみがアクセスでき、サブクラスオブジェクトもこのデータにアクセスできないことを意味するプライベートメンバーで始まります.(下記の通り)
下線で始まる_fooのは直接アクセスできないクラス属性を表し、クラスが提供するインタフェースでアクセスする必要があり、「from xxx import*」でインポートすることはできません.二重下線で始まる__fooクラスのプライベートメンバーを表す.二重下線で始まる__foo__pythonの特殊なメソッド専用の識別子を表す__init__()クラスの構造関数を表す.
class Foo():
    def __init__():
        ...

    def public_method():
        print 'This is public method'

    def __fullprivate_method():
        print 'This is fullprivate_method'

    def _halfprivate_method():
        print 'This is halfprivate_method'

    f = Foo()
    f.public_method() # OK
    f.__fullprivate_method() # Error occur
    f._halfprivate_method() # OK
    f._Foo__fullprivate_method() # OK

上の例から分かるように、f.halfprivate_method()は直接アクセスできますが、確かにそうです.しかしpythonの約束によると、外部で使用しないでprivateと見なすべきで、(どうしても使用しなければならない場合は仕方がない)、良いプログラミング習慣は外部で使用しないことです.また、Pythondocsの説明によると、objectと_objectの役割ドメインは本モジュール内に制限されています.
次のプログラムの出力を見てください.
class A(object):
    def __init__(self):
        self.__private()
        self.public()
    def __private(self):
        print 'A.__private()'
    def public(self):
        print 'A.public()'
class B(A):
    def __private(self):
        print 'B.__private()'
    def public(self):
        print 'B.public()'
b = B()

初めて正しい答えを探したのは:A._private() B.public()
クラスAとクラスBの属性をそれぞれ見てみましょう.
>>> print '
'.join(dir(A)) _A__private __init__ public >>> print '
'.join(dir(B)) _A__private _B__private __init__ public

なぜクラスAには_A__privateという属性があるのでしょうか?そして__private消えた!Pythonのプライベート変数「矯正」についてお話しします.
Pythonは、2つ以上の下線文字で始まり、2つ以上の下線で終わる変数がない変数をプライベート変数とします.プライベート変数は、コード生成前に長いフォーマット(共有)に変換されます.変換メカニズムは、変数の先端にクラス名を挿入し、先端に下線文字を追加することです.これがいわゆるプライベート変数矯正(Private name mangling)である.クラスAのように__private識別子が_A__privateに変換されるのが、前節で出現_A__privateおよび__private消失の原因である.
もう少し余談を言います.
1つは、矯正すると識別子が長くなり、255を超えるとPythonが切断されるため、名前の競合に注意することです.
二つ目は、クラス名がすべて以下の線で命名された場合、Pythonは矯正を実行しないことです.次のようになります.
class ____(object):
    def __init__(self):
        self.__method()
    def __method(self):
        print '____.__method()'

print '
'.join(dir(____)) __class__ __delattr__ __dict__ __doc__ __getattribute__ __hash__ __init__ __method # __module__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __str__ __weakref__ obj = ____() ____.__method() obj.__method() # ____.__method()

では、「A._private()」を出力する理由を振り返ってみましょう.
矯正後、クラスAのコードはこうなります.
class A(object):
    def __init__(self):
        self._A__private()          #     
        self.public()
    def _A__private(self):           #      
        print 'A.__private()'
    def public(self):
        print 'A.public()'

クラスB定義時に上書きされていない__init__メソッドであるため、呼び出されたものは依然としてA.__init__、すなわち実行されたself._A__private()、自然出力「A.__private()」である.
次の2つのコードは説得力を高め、理解を深めることができます.
class C(A):
    def __init__(self): #    __init__ ,    self._A__private
        self.__private()#        _C_private
        self.public()
    def __private(self):
        print 'C.__private()'
    def public(self):
        print 'C.public()'

c = C()
  :
C.__private()
C.public()
class A(object):
    def __init__(self):
        self._A__private()   #            ,     
        self.public()
    def __private(self):
        print 'A.__private()'
    def public(self):
        print 'A.public()'

a = A()
  :
A.__private()
A.public()