web-dev-qa-db-ja.com

Pythonのプライベート変数とメソッド

可能性のある複製:
Pythonでのオブジェクト名の前のシングルアンダースコアとダブルアンダースコアの意味

Pythonのプライベートメンバーとメソッドに、_foo(アンダースコア)と__bar(二重アンダースコア)のどちらを使用すればよいですか?

65
kurikintoki

Pythonには「プライベートメソッド」のようなものはないことに注意してください。ダブルアンダースコアは単なる名前のマングリングです。

>>> class A(object):
...     def __foo(self):
...         pass
... 
>>> a = A()
>>> A.__dict__.keys()
['__dict__', '_A__foo', '__module__', '__weakref__', '__doc__']
>>> a._A__foo()

したがって、__プレフィックスは、マングルが発生する必要がある場合、たとえば、継承チェーンの上位または下位の名前と衝突しないようにする場合に役立ちます。他の用途では、単一のアンダースコアがより良いでしょう、私見。

編集、__の混乱に関して、 PEP-8 はその上で非常に明確です:

クラスがサブクラス化されることを意図しており、サブクラスに使用させたくない属性がある場合は、二重アンダースコアを使用し、後続アンダースコアを使用しない名前を付けることを検討してください。これにより、Pythonの名前マングリングアルゴリズムが呼び出され、クラスの名前が属性名に変換されます。 これにより、サブクラスに誤って同じ名前の属性が含まれている場合に、属性名の衝突を回避できます。

注3:すべての人が名前のマングリングを好むわけではありません。偶発的な名前の衝突を避ける必要性と、上級の発信者による潜在的な使用とのバランスをとるようにしてください。

したがって、サブクラスが誤って同じ名前の独自のメソッドを再定義することを期待しない場合は、使用しないでください。

68
Daniel Kluev

二重アンダースコア。クラス外から__fieldNameを介して簡単にアクセスできないような方法で名前をマングルします。 (フィールドへのアクセスはまだそれほど難しくありませんが。)

class Foo:
    def __init__(self):
        self.__privateField = 4;
        print self.__privateField # yields 4 no problem

foo = Foo()
foo.__privateField
# AttributeError: Foo instance has no attribute '__privateField'

代わりに_Foo__privateFieldからアクセスできます。しかし、それは「私は私に触れないでください」と叫びます。

37
zneak

ダブルアンダースコア。それは名前を台無しにします。この変数には引き続きアクセスできますが、一般的にアクセスするのは悪い考えです。

セミプライベートには単一のアンダースコアを使用し(tells python開発者は「絶対に必要な場合にのみこれを変更」)、完全にプライベートには2倍にします。

9
user407896