I don't know if this is by design (for what reason ?) or if it is a bug, but I have noticed this quite counter-intuitive behaviour :
Doing that, it seems that the logical way to make the __repr__ and __str__ methods, would be to override respectively the parent __repr__ and _str__ methods, and calling them from the inherited versions, but for some reason, it seems that calling super().__str__ leads to call self.__repr__.
I have written the following piece of python-3 code in which I subclass the list class in order to make a class which supports storing names and unnamed fields the same way you can have variable named and unnamed parameters in a function call :
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')
Executing this code in idle-3.5.2 will yield the following result :
>>>
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}"
>>>
As one can see in the second debug lines, the call to `super().__str__()` which I expect to return the result from a call to the `__str__` function from my super class (`list`), will in fact return something which looks very much like the expected return from `self.__repr__()`
It seems that `super().__str__()` calls `self.__repr__()` instead of `list(self).__str__()` or even `super().__repr__()`.
|
@Serhiy Storchaka, this doesn't seem logical, is certainly counter intuitive, and I fear there is a lack of expressivity.
- first of all, this is NOT about having str and repr returning the same at all, but about building the same _kind of_ structure representations for str and repr, but with str of sub elements in __str__, and with repr of sub elements in __repr__.
It is not logical at all and completely counter intuitive, if you explicitely ask str of the superclass, to get repr of the subclass. Getting repr of the superclass would be logical, but not repr of the subclass.
Now, it might happen that I missed another way to write what I tried (casting the object to it's super class with super(), to avoid explicitly naming the superclass) but if there is not, we then have something lacking in terms of expressivity.
|