Вызов super () .__ str__, кажется, вызывает себя .__ repr__ в подклассе списка - PullRequest
0 голосов
/ 05 ноября 2018

Я нашел похожие вопросы, но они довольно старые (6-8 лет) и могут быть устаревшими, и, кстати, в некоторых ответах нет объяснений.

Я написал следующий фрагмент кода Python-3, чтобы создать класс, который поддерживает хранение имен и безымянных полей так же, как вы можете иметь переменные с именованными и безымянными параметрами в вызове функции:

class struct(list):
    def __init__(self, *args, **kwargs):
        super().__init__(args)
        for key, value in kwargs.items():
            setattr(self, key, value)

    def __repr__(self):
        s = super().__repr__()[1:-1]
        for key, val in self.__dict__.items():
            s += ', '+key+'='+repr(val)
        return 'struct('+s+')'

    def __str__(self):
        s = super().__str__()[1:-1]
        print('Debug : super().__str__() = "'+super().__str__()+'"')
        print('Debug : list(self).__str__() = "'+list(self).__str__()+'"')
        print('Debug : s = "'+s+'"')
        for key, val in self.__dict__.items():
            s += ', '+key+'='+str(val)
        return '{'+s+'}'

a = struct(1, 2, 3, a="akeja", b=21, c=True, d="lkj")
print('repr(a)="'+repr(a)+'"\n')
print('str(a)="'+str(a)+'"\n')

Выполнение этого кода в idle-3.5.2 даст следующий результат:

>>> 
 RESTART: struct.py 
repr(a)="struct(1, 2, 3, b=21, d='lkj', a='akeja', c=True)"

Debug : super().__str__() = "struct(1, 2, 3, b=21, d='lkj', a='akeja', c=True)"
Debug : list(self).__str__() = "[1, 2, 3]"
Debug : s = "truct(1, 2, 3, b=21, d='lkj', a='akeja', c=True"
str(a)="{truct(1, 2, 3, b=21, d='lkj', a='akeja', c=True, b=21, d=lkj, a=akeja, c=True}"

>>> 

В этом посте , @Sven Marnach подчеркнул необходимость использования list.__init__(self, args) вместо super().__init__(args) в методе __init__(...), но это ничего не меняет (на самом деле, он писал list.__init__(self, *args), но этот вообще не работает).

Однако, как можно видеть во вторых строках отладки, вызов super().__str__(), который я ожидаю вернуть в результате вызова функции __str__ из моего суперкласса (list), фактически будет вернуть то, что очень похоже на ожидаемое возвращение от self.__repr__()

Я не могу понять, почему self.__repr__(), кажется, вызывается вместо list(self).__str__(). Должен ли я напрямую позвонить __str__() с list(self), как в @Sven Marnach 6лет. совет ? Это правильный способ сделать? Зачем ? Или это просто ошибка, о которой я должен сообщить?

...