2017-10-30 20 views
0

私はPythonで "名前のマングリング"の概念を理解していると思うが、おそらく私が見逃したことがある。ここで私が得る出力二重アンダースコアでクラス属性を継承する

#!/usr/bin/env python 

class Base(object): 
    __data = "Base" 

    @classmethod 
    def func(cls): 
     return "Class name is {}, data is {}".format(cls.__name__, cls.__data) 


class A(Base): 
    __data = "A" 


class B(A): 
    __data = "B" 


print Base.func() 
print A.func() 
print B.func() 

次のコードを見てみましょう

Class name is Base, data is Base 
Class name is A, data is Base 
Class name is B, data is Base 

を、私は各クラスのクラス属性の実際の名前が_<Class name>__dataにマングルされていることを理解しています。だから、例えば、ベースのためには、など、それは_A__dataだろうAのために、_Base__dataだろう

私の質問はいつもcls.__datafuncの内側にそれを正しく継承したクラス(ベース、A及びB)の名前を特定し、ですが、 cls._Base__dataにつながります。何故ですか?私は、__name__がAかBならば、私はクラスAかBの中にいることを知っているので、cls.__dataはそれぞれAかBのどちらかになると思います。私はここで何が欠けていますか?

+2

あなたはそれが**行うには、まさにそれが**はずのだということを逃しています。基底のメソッドの中では、同じ名前のサブクラス属性との衝突を避けるために常に '' _Base ''でマングルされます。 – jonrsharpe

答えて

2

あなたは「欠落」しているわけではありません。逆に、名前のマングリングの意味を「発見」しました。メソッド内の二重のアンダースコアを持つ変数が常にそのクラスと同じクラスで定義された属性を見るようにしますメソッドであり、そのサブクラスのどれもありません。

各サブクラスでオーバーライドされた属性を使用するだけであれば、それは他のすべての属性の通常の動作ですが、2つのアンダースコアが前に付いています。

したがって、の内部で使用されている.__dataという名前は、コンパイル時に_base__dataにマングルされています。

1

あなたが気付いたように、ネームマングリングに使用される名前は、と宣言されたクラスの名前であり、現在のオブジェクトの派生型ではありません。

The documentation for this featureは、(インスタンス変数を使用する外部コードではなく)派生クラスから変数を保護する例を明示的に示しています。

名前のマングリングは、サブクラスがイントラクラスのメソッド呼び出しを破ることなくメソッドをオーバーライドさせるのに役立ちます。たとえば:

class Mapping: 
    def __init__(self, iterable): 
     self.items_list = [] 
     self.__update(iterable) 

    def update(self, iterable): 
     for item in iterable: 
      self.items_list.append(item) 

    __update = update # private copy of original update() method 

class MappingSubclass(Mapping): 

    def update(self, keys, values): 
     # provides new signature for update() 
     # but does not break __init__() 
     for item in zip(keys, values): 
      self.items_list.append(item) 
関連する問題