2016-11-17 31 views
0

最近私はPythonの学習を始めました。そして、継承がどのようにPythonで動作するのか苦労しています。Pythonの継承、属性のエラー

私は2つのクラスを作成しました.1つはAnimal、もう1つはDogです。 DogクラスはAnimalクラスを継承します。私はDogクラスで使用したいAnimalクラスに、名前、高さ、音などの属性をいくつか持っています。私はinit動物クラスのメソッドを使用して属性を設定しています。

class Animal: 
    __name = "" 
    __height = 0 
    __weight = 0 
    __sound = 0 

    def __init__(self, name, height, weight, sound): 
     self.__name = name 
     self.__height = height 
     self.__wight = weight 
     self.__sound = sound 

    def set_name(self, name): 
     self.__name = name 

    def get_name(self): 
     return self.__name 

    def set_height(self, height): 
     self.__height = height 

    def get_height(self): 
     return self.__height 

    def set_weight(self, weight): 
     self.__weight = weight 

    def get_weight(self): 
     return self.__weight 

    def set_sound(self, sound): 
     self.__sound = sound 

    def get_sound(self): 
     return self.__sound 

    def get_type(self): 
     print("Animal") 

    def tostring(self): 
     return "{} is {} cm tall and {} kilograms and says {}".format(self.__name, 
                     self.__height, 
                     self.__weight, 
                     self.__sound) 


cat = Animal("whiskers", 50, 20, "meow") 
print(cat.tostring()) 


class Dog(Animal): 
    __owner = None 

    def __init__(self, name, height, weight, sound, owner): 
     super(Dog, self).__init__(name, height, weight, sound) 
     self.__owner = owner 

    def set_owner(self, owner): 
     self.__owner = owner 

    def get_owner(self): 
     return self.__owner 

    def get_type(self): 
     print("dog") 

    def tostring(self): 
     return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name, 
                         self.__height, 
                         self.__weight, 
                         self.__sound, 
                         self.__owner) 

    def multiple_sounds(self, how_many=None): 
     if how_many is None: 
      print(self.get_sound()) 
     else: 
      print(self.get_sound() * how_many) 
my_dog = Dog("spot", 50, 40, "Ruff", "Derek") 
print(my_dog.tostring()) 

問題は、私は犬のクラスのオブジェクトを使用してすべての属性を印刷しようとすると、エラーが

*line 73, in tostring 
    return '{} is {} cm tall and {} kilograms and says {} His owner is {}'.format(self.__name, 
AttributeError: 'Dog' object has no attribute '_Dog__name'* 

誰も私は、このコードでは、問題を見つけるのを助けることができる」と言って?

答えて

2
表示されています

二重アンダースコアで始まるメンバはプライベートなものなので、cildクラスからアクセスすることはできません単一のアンダースコアを使用する必要がありますPythonはC++やjavaなどの暗黙的アクセス指定子を使用しません。接頭辞は保護されており、名前は__となっています。また、Pythonはあなたがその規約に違反していないことをチェックしません。クラス外の保護されたメソッドまたはプライベートメソッドにアクセスすることは悪い習慣とみなされます。二重のアンダースコアで名前を始めると、特別な方法で変更されます。したがって、Animalクラスと_Dog__nameクラスで使用するとDogで使用すると、__nameは実際に_Animal__nameになります。

+0

ダブルアンダースコアを単一のアンダースコアに変更することで解決できる問題。助けてくれてありがとう ! – Yousaf

1

問題は、名前の二重のアンダースコア接頭辞です。彼らは名前のmanglingを引き起こす。

これらは使用しないでください。彼らはあなたが望むことをしません。

1

Pythonで二重アンダースコアを使用すると、変数「private」が作成されます。他の言語でprivateキーワードを使用した場合と似ています。親クラスの外部にある属性にアクセスするには、それらを削除する必要があります。

Python documentation touches on this subject

クラスのプライベートメンバーのための有効なユースケースは、(すなわち、サブクラスで定義された名前と名前の名前の衝突を回避するため)があるので、このようなメカニズムのための限定的なサポートがあり、ネームマングリングと呼ばれる。 フォームの識別子__spam(少なくとも2つの先頭のアンダースコア、末尾に1つの末尾のアンダースコア)は、テキストで_classname__spamに置き換えられます。classnameは先頭のアンダースコアが取り除かれた現在のクラス名です。。このマングリングは、クラスの定義内で発生する限り、識別子の構文上の位置に関係なく行われます。 (強調鉱山)