[Python-Dev] Concerns about method overriding and subclassing with dataclasses

Antoine Pitrou solipsis at pitrou.net
Fri Dec 29 05:45:21 EST 2017


On Fri, 29 Dec 2017 02:23:56 -0800
Ethan Smith <ethan at ethanhs.me> wrote:
> 
> In a few cases I want to override the repr of the AST nodes. I wrote a
> __repr__ and ran the code but lo and behold I got a type error. I couldn't
> override it. I quickly learned that one needs to pass a keyword to the
> dataclass decorator to tell it *not* to auto generate methods you override.
> 
> I have two usability concerns with the current implementation. I emailed
> Eric about the first, and he said I should ask for thoughts here. The
> second I found after a couple of days sitting on this message.
> 
> The first is that needing both a keyword and method is duplicative and
> unnecessary. Eric agreed it was a hassle, but felt it was justified
> considering someone may accidentally override a dataclass method. I
> disagree with this point of view as dataclasses are billed as providing
> automatic methods. Overriding via method definition is very natural and
> idiomatic.

Agreed.  We shouldn't take magic too far just for the sake of
protecting users against their own (alleged) mistakes.  And I'm not
sure how you "accidentally" override a dataclass method (if I'm
implementing a __repr__ I'm doing so deliberately :-)).

> The second concern, which I came across more recently, is if I have a base
> class, and dataclasses inherit from this base class, inherited __repr__ &
> co are silently overridden by dataclass. This is both unexpected, and also
> means I need to pass a repr=False to each subclass' decorator to get
> correct behavior, which somewhat defeats the utility of subclassing. Im not
> as sure a whole lot can be done about this though.

Agreed as well.  If I make the effort of having a dataclass inherit
from a base class, I probably don't want the base class' methods to be
silently overriden by machine-generated methods.  Of course, that can
be worked around by using multiple inheritance, you just need to be
careful and add a small amount of class definition boilerplate.

I would expect dataclass parameters such as `repr` to be tri-state:

* repr=None (the default): only provide a machine-generated
  implementation if none is already defined (either on a base class or
  in the dataclass namespace... ignoring runtime-provided defaults such
  as object.__repr__)
* repr=False: never provide a machine-generated implementation
* repr=True: always provide a machine-generated implementation, even
  overriding a previous user-defined implementation

Regards

Antoine.




More information about the Python-Dev mailing list