下線と下線の違い
4435 ワード
主に4つのネーミングが存在します
コアスタイル:アンダースコアを変数名の先頭にしないでください.
下線は解釈器に特別な意味を持ち、組み込み識別子で使用される記号であるため、プログラマは変数名の開始として下線を使用しないことをお勧めします.一般に、変数名_objectは「プライベート」とみなされ、モジュールやクラス外では使用できず、「from module import*」でインポートできません.変数がプライベートの場合、_objectは変数を表すのに良い習慣です.
下線+クラス名、eg:
「単一下線」で始まるメンバー変数を保護変数と呼びます.これは、クラスオブジェクトとサブクラスオブジェクトだけがこれらの変数にアクセスできることを意味します.二重下線」は、クラスオブジェクトのみがアクセスでき、サブクラスオブジェクトもこのデータにアクセスできないことを意味するプライベートメンバーで始まります.(下記の通り)
下線で始まる
上の例から分かるように、f.halfprivate_method()は直接アクセスできますが、確かにそうです.しかしpythonの約束によると、外部で使用しないでprivateと見なすべきで、(どうしても使用しなければならない場合は仕方がない)、良いプログラミング習慣は外部で使用しないことです.また、Pythondocsの説明によると、objectと_objectの役割ドメインは本モジュール内に制限されています.
次のプログラムの出力を見てください.
初めて正しい答えを探したのは:A._private() B.public()
クラスAとクラスBの属性をそれぞれ見てみましょう.
なぜクラスAには
Pythonは、2つ以上の下線文字で始まり、2つ以上の下線で終わる変数がない変数をプライベート変数とします.プライベート変数は、コード生成前に長いフォーマット(共有)に変換されます.変換メカニズムは、変数の先端にクラス名を挿入し、先端に下線文字を追加することです.これがいわゆるプライベート変数矯正(Private name mangling)である.クラスAのように
もう少し余談を言います.
1つは、矯正すると識別子が長くなり、255を超えるとPythonが切断されるため、名前の競合に注意することです.
二つ目は、クラス名がすべて以下の線で命名された場合、Pythonは矯正を実行しないことです.次のようになります.
では、「A._private()」を出力する理由を振り返ってみましょう.
矯正後、クラスAのコードはこうなります.
クラスB定義時に上書きされていない
次の2つのコードは説得力を高め、理解を深めることができます.
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()