Skip to content

Add _repr to named tuples #129343

@bswck

Description

@bswck

Feature or enhancement

Proposal:

This issue aims to propose a new feature on top of fixing gh-85795.

gh-85795 stems from the necessity of using super() inside methods of typing.NamedTuple subclasses.
The documentation does not explicitly state it as unsupported, nor does it disrecommend the use of it.
Consequently, that behavior should be supported and the converse is considered a bug.

As in the StackOverflow question here, the developer tried their own implementation of __repr__ in the subclass.
And that's how I encountered the issue, too! I think it is very useful to be able to override the default NamedTuple representation and add additional info on top of it/tweak it somehow. For that reason, one would intuitively use super().__repr__(), since we inherit from NamedTuple.

However, that is impossible with the current model of behavior in typed named tuples.
Typed named tuples are constructed from the existing implementation of tuple subclass factory collections.namedtuple that does not insert anything other than tuple above the final class in the MRO. Inheritance from NamedTuple is only possible due to __mro_entries__ hacks on the typing.NamedTuple function. To reference the default representation method of named tuples via super().__repr__(), a middleman class representing the default implementations of named tuple methods between the underlying class and tuple would be necessary. That is currently most likely impossible for backward compatibility reasons, something I learned from #126706 (comment), and does not appeal to me in terms of cost/benefit ratio.

Hence, since __repr__ is the only default method of NamedTuple useful to be referenced in typing.NamedTuple subclasses, and all other come from tuple or object, I propose adding _repr to the named tuple interface. The default __repr__ implementation would be a direct wrapper of it. In typing.NamedTuple, _repr could not be overridden, but __repr__ could, to enable extendability with an optional reuse of _repr.

In NamedTuple subclasses all super().__repr__() calls would resolve to tuple.__repr__().

This introduces no breaking changes, is additive only and retains the stable behavior of default __repr__ of named tuples.
With proper documentation, it can hint advanced named tuple users in how to create their own implementations of __repr__ reusing the existing __repr__ default implementation.

Example

class Import(NamedTuple):
    target: str

    def __repr__(self) -> str:
        # super().__repr__() -> ('target',)
        # self._repr() -> Import(target='target')
        return f'<Token {self._repr()}>'  # <Token Import(target='target')>

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions