On 04/05/2019 21:58, Ricky Teachey wrote:
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.

dict(myobj) is only defined for mapping objects. For everything else, "dict-making" *isn't* addressed.

(Also, it's not a protocol. I think what you want is a protocol, but you aren't specifying it well enough for me to grasp.)

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.

Actually dict() would be the place to do this, surely? If all you want is to add dataclasses and namedtuples to the list of things dict() copes with, that's entirely reasonable. If you have a list of obviously mapping-like things dict() should cope with, that's fine. If you want someone else to go do the work for you, that's less fine, but hey, someone might think it's an interesting thing to do. If you want dict() to cope with arbitrary objects (which you still appear to), you need to say how.

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.

I still think this is an unhelpful starting place. I would actually be hesitant to use an API that just said "oh, throw anything at me, I'll cope." I'd much rather use something that told me what format it expected data in, what I need to conform to, and do any conversion myself. With half an ounce of luck I'll be able to arrange to get the data in the right format in the first place and avoid a whole unnecessary layer of processing.


For user-defined protocols, we simply leave HOW to dict-ify to the
caller via the factory_dict argument (if it is provided).

I am minded of the Larson cartoon, "...and now a miracle occurs..." This is the first time you've mentioned this argument (to dict(), presumably?).

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.

Right.  So what you want is to add a keyword argument to dict() such that
    dict(obj, factory_dict=dict_me_harder)

calls dict_me_harder(obj) if obj is not a type dict() knows how to deal with natively, expecting it to return a new dict or raise an exception. Is that right?

--
Rhodri James *-* Kynesim Ltd
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to