1

Python の抽象クラスから継承するクラスがあります。

class MyAbstractClass():
    __Var1 = 0

    def __init__(self):
        pass

class MySubClass(MyAbstractClass):
    def __init__(self):
        MyAbstractClass.__init__(self)

    def MyFunc(self):
        print self.__Var1

これにより、次のエラーが発生します。

AttributeError: MySubClass instance has no attribute '_MySubClass__Var1'

これら 2 つのクラスは別のファイルにあることに注意してください。

私は周りを検索しましたが、ほとんどの提案は、コードを「super()」の使用から親の明示的な名前に変更することでした。ただし、まだこのエラーが発生しています。

どうしたの?

4

3 に答える 3

4

表示されるのはmangling という名前です。二重下線で始まる名前は、サブクラスでの名前の衝突を避けるために特別な方法で処理されます。

基本的に、クラスに属性がある場合は常に、継承時の名前の衝突を避けるため__some_nameに自動的に名前が変更されます。_YourClass__some_name

dir()これは、次の関数を使用して確認できます。

>>> class MyClass(object):
...     __var = 1
... 
>>> dir(MyClass)
['_MyClass__var', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

リストに が含まれていないことに注意してください。__var_MyClass__var

修正は簡単です:二重下線で始まる変数名を使用しないでください。変数をプライベートとしてマークしたい場合、慣習として単一のアンダースコアを使用します。

名前マングリングの主な目的は、サブクラスとの名前空間の衝突を避けることです。

>>> class MyClass(object):
...     def __init__(self, val):
...             self._value = val
... 
>>> class MySubclass(object):
...     def __init__(self, val):
...             super(MyClass, self).__init__(val)
...             self._value = val ** 2  #this hides the base class attribute!
... 

基本クラスがサードパーティのライブラリからのものである場合、それらは API の一部ではないため、どのプライベート属性が定義されているかを知ることができないことに注意してください。で確認するとdir、どの名前が使用されているかについてのヒントしか得られませんが、それらは実装の詳細であるため、予告なしに変更される可能性があります。

属性を非公開として「マーク」するためにこれを使用しないでください。Pythonの規則では、単一のアンダースコアで始まる属性はプライベートです。

関連するトピックでは、名前__something__の先頭と末尾の両方に二重アンダースコアがあるフォームの名前も特別に扱われます。それらのいくつかは特別なメソッドを実装しているため、この種の識別子は決して使用しないでください。

于 2013-02-26T22:10:04.170 に答える
2

二重アンダースコアは、変数名を意図的に難読化し、セミプライベートにします。詳細については、 http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-referencesを参照してください。

この問題を解決するには、に変更__Var1_Var1ます。

于 2013-02-26T22:12:56.243 に答える
1

Var1 の前の 2 つのアンダースコアは、名前マングリングを行います。実行時__Var1は のようになり_MySubClass__Var1ます。

名前を _Var1 に変更して、アンダースコアを 1 つ付けてください。

名前マングリングは、Python が一種のプライベート変数を作成する方法です。名前空間の衝突を防ぐためです。

ここにこれに関するいくつかの詳細があります

于 2013-02-26T22:12:44.280 に答える