2013-07-30 3 views
1

Как переопределить элемент базового класса в моем производном классе, чтобы обращения к этому члену вызывали вызывающий член? Рассмотрим следующий пример? __tmp переписывается в B и должны вернуться в случае вызова tmp()Python: скрыть элемент базового класса в производном классе

class A: 
    __tmp = {"A" : 1, 
      "B" : 2} 
    def tmp(self): 
     return self.__tmp 

class B(A): 
    __tmp = {"A" : 10, 
      "B" : 20} 
    def __init__(self): 
     super().__init__() 

b = B() 
print(b.tmp()) # Expect to print {'A': 10, 'B': 20} here 

ответ

3

Не используйте затемненный имена переменных:

class A: 
    _tmp = {"A" : 1, 
      "B" : 2} 
    def tmp(self): 
     return self._tmp 

class B(A): 
    _tmp = {"A" : 10, 
      "B" : 20} 
    def __init__(self): 
     super().__init__() 

b = B() 
print(b.tmp()) # Works as expected 

Проблема заключалась в том, что self.__tmp это имя-искажаются за кулисами python и разрешается до self._A__tmp, так как tmp - это метод класса A. Вы хотели self._B__tmp. Если бы вы переопределили метод tmp в B, это сработало бы, но это глупый способ сделать это, поскольку он побеждает одну из целей наследования - избегая дублирования кода.

Зарезервировать переменные __private, если вы хотите избежать имя столкновения с атрибутами подклассов. В этом случае вы действительно хотите achive такое коллизирование имен.

Если вы хотите, чтобы атрибут был закрытым, достаточно одного символа подчеркивания, начиная с we're all consenting adults here.

+0

Спасибо, что работает! Что именно вы подразумеваете под «обфускацией имен переменных»? Двойное подчеркивание или просто 'tmp' из этого примера? – Razer

+1

Использование двух ведущих подчеркиваний атрибута заставляет его искажать имя. Это подробно описано в [pep-8] (http://www.python.org/dev/peps/pep-0008/) (поиск «ведущего подчеркивания»). –

0

Из описания это не ясно для меня, почему нужно хотеть и иметь смысл. Похож на довольно странный дизайн. Но, тем не менее, почему бы вам просто не перезаписать геттер?

class A(object): 
    __tmp = {"A" : 1, 
      "B" : 2} 
    def tmp(self): 
     return self.__tmp 

class B(A): 
    __tmp = {"A" : 10, 
      "B" : 20} 
    def __init__(self): 
     super(B, self).__init__() 

    def tmp(self): 
     return B.__tmp 


b = B() 
print(b.tmp()) # Expect to print {'A': 10, 'B': 20} here 
+0

Реализация этого не имеет смысла. Это всего лишь ненужная работа. Цель этого проекта состоит в том, чтобы иметь базовый класс 'A', который предоставляет некоторые имена (' __tmp'). Подклассы могут определять свои собственные имена или принимать имена базового класса. Тем не менее доступ к этому должен вернуть правильные. – Razer

Смежные вопросы