Проблема с доступом к приватным полям базового класса

Рейтинг: 1Ответов: 2Опубликовано: 11.10.2014

Код:

class Parent(object):
    def __init__(self):
        self.__field = 13 # private field for inner uses only

class Child(Parent):
    """docstring for Child"""
    def __init__(self):
        super(Child, self).__init__()

    def ChildMethodWhichUsingParentField(self):
        return self.__field

if __name__ == '__main__':
    c = Child()
    c.ChildMethodWhichUsingParentField()

Вывод интерпретатора:

Traceback (most recent call last):
  File "foo.py", line 20, in <module>
    c.ChildMethodWhichUsingParentField()
  File "foo.py", line 16, in ChildMethodWhichUsingParentField
    return self.__field
AttributeError: 'Child' object has no attribute '_Child__field'

Я, конечно, могу использовать property для этих целей, но всё-таки хотелось бы обращаться к родительским атрибутам напрямую и не писать при этом self._Parent__field.

Ответы

▲ 2

Когда идешь в универ, говорят "забудь все, чему учили в в школе". Когда идешь работать, говорят "забудь все, чему тебя учили в универе". К чему это я.

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

Делать приватную переменную, и навешивать на него свойство это неправильно в принципе. Геттеры и сеттеры, которые не скрывают никакой реализации это свидетельство плохого дизайна.

А как же правильно?

Сделайте переменную с нижнего подчеркивания, всем будет понятно что это не публичный интерфейс, и лучше ее не трогать. А если тронут, и не покроют это место тестами - сами себе Буратины. И не надо быть готовым, что приватную переменную кто нибудь поменяет, это все должно быть на совести того, кто пользуется этим классом. Создавая такую переменную вы тем самым создаете контракт. Нарушая этот контракт странно ожидать от класса корректного поведения.

▲ 1

Вы неправильно обращаетесь с приватными полями. Примерно так:

self.__a=0 # свойство

@property
def a(self):
    return self.__a

@a.setter
def a(self, val=None):
    self.__a=val

@a.deleter
def a(self):
    del(self.__a)