On Wed, Jan 22, 2020 at 9:17 AM Andrew Barnert <abarn...@yahoo.com> wrote:
>
> On Jan 21, 2020, at 12:29, Chris Angelico <ros...@gmail.com> wrote:
> >
> > For non-dataclass classes, it would be extremely helpful to have an
> > easy helper function available:
> >
> > class Spam:
> >   def __repr__(self):
> >       return reprlib.kwargs(self, ["quality", "recipe", "ham"])
> >
> > The implementation for this function would be very similar to what
> > dataclasses already do:
> >
> > # in reprlib.py
> > def kwargs(obj, attrs):
> >   attrs = [f"{a}={getattr(obj, a)!r}" for a in attrs]
> >   return f"{obj.__class__.__qualname__}({", ".join(attrs)})"
> >
> > A similar function for positional args would be equally easy.
>
> I like this, but I think it’s still more complex than it needs to be for 80% 
> of the cases (see below)

IMO that's not a problem. The implementation of reprlib.kwargs() is
allowed to be complex, since it's buried away as, well, implementation
details. As long as it's easy to call, that's all that matters.

> while for the other 20%, I think it might make it too easy to get things 
> wrong.

Hmm. I kept it completely explicit - it will generate a repr that
shows the exact attributes listed (and personally, I'd often write it
as "quality recipe ham".split()), and left the idea of automatic
detection as a bikesheddable option.

> > Bikeshedding opportunity: Should it be legal to omit the attrs
> > parameter, and have it use __slots__ or fall back to dir(obj) ?
>
> This makes things even more dangerous. It’s very common for classes to have 
> attributes that aren’t part of the constructor call, or constructor params 
> that aren’t attributes, and this would give you the wrong answer.
>
> It would be nice if there were a safe way to get the constructor-call-style 
> repr. And I think there might be for 80% of the types—and the rest can 
> specify it manually and take the risk of getting it wrong, probably.
>
> One option is the pickle/copy protocol. If the type uses one of the newargs 
> methods, you can use that to get the constructor arguments; if it uses one of 
> the other pickling methods (or can’t be pickled), this just doesn’t work.
>
> You could also look at the inspect.signature of __init__ and/or __new__. If 
> every param has an attribute with the same name, use that; otherwise, this 
> doesn’t work.
>
> And if none of the automatic ways worked and you tried to use them anyway, 
> you get an error.

This is definitely getting into the realm of magic. The question is,
is it worth the convenience? I'd be +0.25 for the magic. Also, that
can always be added in the future. If the explicit-list-of-attributes
form is useful but too fiddly, it would be possible to add a stated
default of "figure it out by magic", and then the exact magic can be
redefined at will.

> But it would be nice if this error were at class-defining time rather than at 
> repr-calling time, so maybe a decorator is actually a better solution?
>
>     @reprlib.defaultrepr
>     class Spam:
>

Also a definite possibility.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/V4NAISJVOCEQFGH4ZDZTQGUR7B4Q7W5M/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to