2016-12-31 3 views
1

Так что я продолжаю получатьОбъект not inheretinting функции от суперкласса?

error: " AttributeError: 'Dog' object has no attribute '_Dog__name'"

Дело в том, print(spot.get_name()) работает отлично. Также, когда я пробовал spot.multiple_sounds(), это не так. Я думаю, что проблема заключается в том, что я пытаюсь вызывать атрибуты объектов из суперкласса в функции в определении объекта. Однако я не понимаю, почему. Я делаю все это из учебника, и код идентичен его. Я думаю, это может быть потому, что он использует python2.x, и я использую spyder python3.x, но я понятия не имею. Любая помощь приветствуется.

import random 
import os 
import sys 

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

    def __init__(self,name,height,weight,sound): 
     self.__name = name 
     self.__height = height 
     self.__weight = 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', 33, 10,'Meow') 

print(cat.toString()) 

class Dog(Animal): 

    __owner = "" 

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

    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 says {} and 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.getsound()) 
     else: 
      print(self.getsound()*how_many) 

spot = Dog("Spot", 53, 27, "Ruff", "Some Guy") 
print(spot.get_name()) 
print(spot.toString()) 
+0

Небольшие примеры лучше ... вы можете обрезать большую часть, что из в пример программы, который легче читать, но демонстрирует проблему. – tdelaney

+1

@ e4c5 - Я не думаю, что это достаточно близко для дурака. В основном речь идет о специальных методах, таких как '__init__'. – tdelaney

+0

ok @tdelaney retracting – e4c5

ответ

2

В питоне, __fieldName эмулирует частное поле, означает два подчеркивания, что в имени поля. Таким образом, такие поля не могут быть получены из производных классов, но вы все равно можете получить их с помощью getter.

+0

Итак, я удалил двойное подчеркивание из всех переменных, и это сработало, но как бы я мог использовать getter для их вызова? – whydoesmycodehateme

+0

self.get_name(), если вам нужна приватная переменная в дочернем классе, ваш получатель является общедоступным –

0

Имена, начинающиеся с двойных подчеркиваний и заканчивающиеся нулевым или 1 подчеркиванием, являются ответом python на частные переменные. Python направляет их в __Class_name, чтобы сделать их закрытыми для класса, а не его унаследованных подклассов. Идея состоит в том, чтобы позволить вам иметь имена внутри класса без подкласса с ними. Очевидно, что это легко подорвать, используя известное имя munged, но тогда python является динамическим языком.

См Private Variables

1

Любой атрибут или метод, который начинается с «__» является только доступны под этим именем из функций в том же классе. Не из других классов, даже не из подклассов.

class A: 
    def __init__(self, name): 
     self.__name = name 

    def get_name(self): 
     return self.__name 

class B(A): 
    def get_name_capitalized(self): 
     return self.__name.upper() 

b = B('Bob') 
print(b.get_name()) # prints 'Bob' 
print(b.get_name_capitalized()) # fails 

В приведенном выше коде, вызывая A.get_name() доступ к атрибуту экземпляра __name успешно. Но B.get_name_capitalized() с ошибкой «Объект AttributeError: 'B» не имеет атрибута «_B__name» ». «__» имена искажаются компилятором, так что они недоступны как есть. Если код в get_name_capitalized изменяется на:

return self._A__name.upper() 

тогда он будет работать, так что эти атрибуты являются доступными, но вы должны использовать искаженное имя, чтобы получить на них.

То есть, как Python было с 1.x, и нет ничего нового с Python 3.