io.StringIO перезаписывает унаследованное свойство - делать или не делать? - PullRequest
0 голосов
/ 18 февраля 2012

Я создал подкласс из StringIO для создания класса MockFile.В производном классе должен быть атрибут "name", но создание этого атрибута приводит к AttributeError.

. Озадаченный, я выполнил поиск __dict__ и обнаружил, что уже был name -ключ.Итерируя по __mro__, я нашел свойство с именем 'name', очевидно доступное только для чтения в классе io.TextIOWrapper.

Итак, у меня есть два основных вопроса:

  1. для чего предназначено это свойство 'name'
  2. безопасно ли перезаписывать его присваиванием settattr?

Пример кода для полноты:

class MockFile(StringIO): 
    def __init__(self, name, buffer_ = None):
        super(MockFile, self).__init__(buffer_)
        self.name = name     
>>> mfile = MockFile('stringio.tmp', u'#MockFile')

ведет к:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
AttributeError: can't set attribute

1 Ответ

1 голос
/ 18 февраля 2012

Свойство name io.StringIO в Python 2.6 происходит из иерархии классов в модуле io. Это довольно сложная установка с наследованием и композицией, а свойство name используется для передачи имен из базовых объектов различным оберткам и специализациям. Однако фактическое свойство io.StringIO отсутствует в Python 2.7 и более поздних версиях, так что вы можете спокойно затенять его в своем подклассе.

Вы не можете использовать setattr() для установки свойства больше, чем фактическое назначение - settattr() и назначение атрибутов работают одинаково. Природа свойства не позволяет вам затенять свойство baseclass с атрибутом экземпляра (не делая больше.) Однако вы можете определить собственное свойство с тем же именем или обмануть Python, чтобы не видеть свойство в первую очередь:

class MockFile(StringIO):
    name = None
    def __init__(self, name, buffer_ = None):
        super(MockFile, self).__init__(buffer_)
        self.name = name     
...