2015-01-28 3 views
5

Я новичок в python, и я не был уверен, что я делаю это правильно. У меня есть базовый класс A и унаследованный класс B.Наследование свойств Python

class A(object): 

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

    @property 
    def name(self): 
     return self.__name 

    @name.setter 
    def name(self, name): 
     self.__name = name 

class B(A): 
    def __init__(self, name): 
     super(NominalValue, self).__init__(name) 

    @property 
    def name2(self): 
     return self.__name2 

    @name2.setter 
    def name2(self, n): 
     self.__name2 = n 

    def toString(): 
     print self.__name + self.__name2 

if __name__ == "__main__": 
    instance = B('name'); 
    instance.toString() 

При запуске этого он жалуется, что класс B не имеет атрибут __name.

AttributeError: 'B' object has no attribute '_B__name' 

Я явно не делаю наследование правильно. Как вы относитесь к правильному унаследованию свойств и избегаете повторения атрибутов в унаследованном классе?

+3

Двойное подчеркивание имеет [специальное значение] (https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references), которое мешает вашему наследованию. Чтобы получить доступ к атрибуту '__name' суперкласса, я думаю, вам нужно называть его« self._A__name ». –

+2

Как упоминает 6502 в своем ответе, вы не должны обязательно * ПЛАНИРОВАТЬ * при написании имущества для своего класса.Это одна из сильных сторон свойств в Python: очень легко преобразовать атрибут в свойство «на лету». Если это не доказывает, что вам нужна пользовательская логика для получения, установки или удаления атрибута - не используйте свойство для этого. –

ответ

7

Атрибуты, начинающиеся с двух символов подчеркивания, таких как ваши __name, обозначаются как частные переменные. Фактически нет ЗАЩИТА (то есть: если вы можете найти его, вы можете получить к нему доступ), но они не могут быть легко доступны для доступа. More information about that can be found on the docs page

Любой идентификатор формы __spam (по крайней мере, два ведущих подчеркивания, не более одного знака подчеркивания) является текстуально заменен _classname__spam, где classname является текущее имя класса с начальным символом подчеркивания (ов) раздели.

Из-за этого, даже если вы наследуя A «S __name атрибута, не имеет атрибут __name в любом объекте типа B. У вас есть атрибут _A__name. Вот как имя-коверкая работы: __attributename становится _classname__attributename

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

5

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

Большинство программистов на Python не знают, почему они особенные, и они все еще могут жить счастливой и продуктивной жизнью программирования. Они также объективно уродливы ... не так ли?

Обратите внимание, что в Python вы не начинаете использовать геттер и сеттер только для удовольствия. Просто начните с члена данных и перейдите к свойствам, когда (и только если) необходимо. Написание кода для геттера, который просто возвращает член и для сеттера, который просто мутирует, - это вздор. Когда (и если) вам нужно будет сделать специальную обработку при доступе к члену, измените их на свойства, и вам не придется менять код с помощью вашего класса.

С технической стороны объяснения Python просто добавляет имя класса к атрибутам, начинающимся с двойного подчеркивания, чтобы избежать нежелательных столкновений с одинаково названными атрибутами в других классах. Однако такая проблема не так распространена, поэтому большинство программистов на Python никогда не нуждались в этой функции.