Ошибка атрибута в подклассе Python при доступе к родительскому атрибуту

#python

#python

Вопрос:

Я хотел бы добавить некоторые функциональные возможности в класс PlyElement, создав подкласс PlyElementPlus . Я предпочитаю предоставить вам реальный фрагмент кода, потому что он может быть более полезным для понимания того, что происходит. В любом случае проблема связана с классами и защищенными переменными.

 class PlyElementPlus(PlyElement):
    def __init__(self, element):
        super().__init__(element.name, element.properties, element.count)
        self.names = list(element.data.dtype.names)
        self.types = [str(element.data[n].dtype) for n in self.names]

mesh = PlyData.read(fname)         # This is a PlyData
vertex = mesh['vertex']            # This is a PlyElement
print(vertex.data[0]['x'])         # works 
>>> -1.60847
print(vertex[0]['x'])              # direct indexing works 
>>> -1.60847

vertex = PlyElementPlus(vertex)     # This is a PlyElementPlus
print(vertex.data[0]['x'])          # doesn't work
>>> AttributeError: 'PlyElementPlus' object has no attribute '_data'
  

Здесь есть часть PlyElement, которая может быть полезна для понимания ошибки:

 class PlyElement(object):
    def __init__(self, name, properties, count, comments=[]):
    ...
    
    def _get_data(self):
        return self._data

    def _set_data(self, data):
        self._data = data

    data = property(_get_data, _set_data)
    
    def __getitem__(self, key):
        return self.data[key]

    def __setitem__(self, key, value):
        self.data[key] = value
  

Другие методы или атрибуты, которые не являются «защищенными», могут вызываться из моего подкласса, а «данные» — нет. Более того, данные доступны путем прямого индексирования, и я бы хотел, чтобы мой подкласс воспроизводил то же поведение.
Вы можете мне помочь?

Комментарии:

1. Это не имеет никакого отношения к тому, что материал «защищен» или нет. У вашего объекта просто нет data атрибута. Значение data никогда не задавалось.

Ответ №1:

Это происходит, поскольку по умолчанию a PlyElement не имеет атрибута _data , который требуется при доступе .data :

     def _get_data(self):
        return self._data

    data = property(_get_data, _set_data)]
  

_data Атрибут доступен после PlyElements._read() вызова, что выполняется PlyData при вызове его .read() метода; Строка 397 в этом файле.

Итак, как сказано в документации,

     A client of this library doesn't normally need to instantiate this
    directly, so the following is only for the sake of documenting the
    internals.
  

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

 self._data = element._data
  

к вашему __init__() .