__setattr__への「名前」パラメーターにクラスが含まれるのはなぜですか?
質問
次のコード:
class MyClass():
def test(self):
self.__x = 0
def __setattr__(self, name, value):
print name
def __getattr__(self, name):
print name
raise AttributeError(name)
x = MyClass()
x.test()
x.__y
出力:
_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y
ドキュメントは、「名前」が「属性の名前」であると述べることを完全に役に立たないが、何らかの理由で、それを設定しているのか、それを取得しているのかによって異なる。
私が知りたいのは:
- 私はここで根本的に間違っていることをしていますか?
- どうすれば入手できますか
x
ではなく最初のケースで_MyClass__x
?
解決
ダブルアンダースコアは、マングリングという名前を呼び出します。名前のマングルが必要ない場合は、ダブルアンコアを使用しないでください
オブジェクト名の前のシングルおよびダブルアンダースコアの意味は何ですか?
から Pythonドキュメント
9.6。プライベート変数
オブジェクト内を除いてアクセスできない「プライベート」インスタンス変数は、Pythonには存在しません。ただし、ほとんどのPythonコードが続くコンベンションがあります。アンダースコアが付いた名前(例:
_spam
)APIの非公開部分(関数、メソッド、またはデータメンバーであるかどうか)として扱う必要があります。実装の詳細と見なされ、予告なく変更する必要があります。クラスプライベートメンバーには有効なユースケースがあるため(つまり、サブクラスで定義された名前の名前の名前の衝突を回避するため)、名前マングリングと呼ばれるそのようなメカニズムに対するサポートは限られています。フォームの識別子
__spam
(少なくとも2つの主要なアンダースコア、せいぜい1つの後続のアンダースコア)はテキストで置き換えられます_classname__spam
, 、ClassNameは、先頭のアンダースコアが剥がれた現在のクラス名です。このマングルは、クラスの定義内で発生する限り、識別子の構文位置に関係なく行われます。マングリングルールは、主に事故を避けるために設計されていることに注意してください。プライベートと見なされる変数にアクセスまたは変更することも可能です。これは、デバッガーなどの特別な状況でも役立ちます。
コードが渡されたことに注意してください
exec
,eval()
またexecfile()
呼び出しクラスのクラス名が現在のクラスであるとは考えていません。これは、グローバルステートメントの効果に似ており、その効果は同様にバイトコンパイルされたコードに制限されています。同じ制限が適用されますgetattr()
,setattr()
とdelattr()
, 、および参照するとき__dict__
直接。
他のヒント
なぜこれが起こるのか正確にはわかりませんが、あなたが使用する場合 _x
それよりも __x
予想通りに機能します。