[Python-ideas] add an additional dataclasses.asdict option for non-dataclasses

Ricky Teachey ricky at teachey.org
Sat May 4 16:58:43 EDT 2019


> Are "asdict" APIs all that common?

There are at least two in the std lib: namedtuple._asdict(), and
dataclasses.asdict. I assume there are others I'm not aware of.

> Conventionally you would get the caller to do this...
> Anything else involves lots of guesswork...

> The problem with "casting" a generic non-dataclass object to a dict is
> that it's not remotely obvious how you do that.  What key do you use if
> your object is a simple int or string?  If you have even a
> straightforward user class aren't just using "thing.__dict__", what
> attributes do or do not make it into the dictionary?

I get the impression that what I am suggesting wasn't clear. Let me
approach it from a different direction.

The language already provides the mapping protocol for user defined
dict-making; ie, dict(myobj). So "this is how you define dict-making"
rabbit hole is not only not worth going down, it's already been
addressed for a very long time.

The problem I want to address is very specific and two pronged:

1. some of the std lib modules DON'T USE the mapping protocol (for
various very legitimate reasons)

2. some user-defined types also don't use the mapping protocol, also
often for legit reasons

Therefore the proposal is not to guess anything at all. The idea is to
rigorously track all the existing dict APIs that have been put into
the std lib over the years into a dict-making convenience function,
since, for example, dict(my_dataclass) and dict(my_namedtuple) are
(legitimately) broken.

One can then confidently apply that asdict() convenience function
without having to resort to a complicated string of if statements that
might not even catch all cases. The language already does this kind of
cataloging for other things, like getting a list of all the reserved
keywords. Why not catalog all the std lib dict-making APIs into a
dict-making convenience function, too?

For user-defined protocols, we simply leave HOW to dict-ify to the
caller via the factory_dict argument (if it is provided). If it isn't
provided, one of the following would happen:

 - raise an error -- similar or even identical to, perhaps, the error
raised for dict("foo") or dict(42)

 - use the default dict_factory (which is dict; identical to above,
but succeeds if there is a dict-casting protocol already implemented)

I favor the second, but I'm not dogmatic about which of those would be better.

Again: no interest in trying to guess at user defined dict-making APIs
as such, aside from allowing the caller to provide that API themselves
if they so wish.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20190504/d76ef451/attachment-0001.html>


More information about the Python-ideas mailing list