On Sat, May 11, 2019 at 8:23 PM Eric V. Smith <e...@trueblade.com> wrote:
> >> https://www.python.org/dev/peps/pep-0557/#why-not-just-use-namedtuple >> > > you would know, but that reference talks about why they are not the same > as NamedTuple. > > > That section mentions why they’re not iterable. Search on “iterable”. > Sure, but in the context of the difference with NamedTuple: """ Instances are always iterable, which can make it difficult to add fields. If a library defines: Time = namedtuple('Time', ['hour', 'minute']) def get_time(): return Time(12, 0) Then if a user uses this code as: hour, minute = get_time() then it would not be possible to add a second field to Time without breaking the user's code. """ which is a great argument for why you wouldn't want dataclasses to iterate on the *values* of the fields, which is what NamedTuple does. In fact, beyond iteration, NamedTuple, IS a tuple, so: - the number of "fields" matters, - the order of the "fields" matters, - it's the values that really matter -- the field names are incidental. None of this (intentionally) applies to dataclasses - which is what i took as the point of that section of the PEP. But I see dataclasses as being more analogous to a dict than a tuple: - The field names matter - The order of the fields does not matter (the current state of the dict implementation not withstanding) So *if* dataclasses were to be iterable, then I'd think they should either implement the Mapping protocol (which would make them, similar to NamedTuple, a drop-in replacement for a dict, or iterate over (field_name, value) pairs. which would not introduce the issues staed in teh PEP with the iterability of NamedTuple. Note: I am NOT advocating for making dataclasses a Mapping -- I believe in a clear separation between "data" and "code" -- dicts are suitable for data, and dataclasses are suitable for code. Given PYthon's dynamic nature, this isn't always a clear boundary, but I think it's a better not to purposely make it even less clear. Others may have a different take on this -- it could be kind of a cool way to make a dict with extra functionality, but I think that's ill-advised. > if dataclasses *were*iterable, they almost certainly wouldn't iterate over > the values alone. > > That wouldn’t make a difference. The given NT example would still be a > problem. > you know, I'm embarrassed to say that I read through a lot of this thread wondering what the heck an NT is ;-) -- but now I got it. but I don't think the NT example is relevant here -- it's an issue with NT, because NTs are designed to be, and used as drop in replacements of tuples, and a lot of code out there does use tuples for "unpacking" assignments. But I'm going to hazard a guess that it's pretty rare for folks to do: def get_time(): ... return {"hour", 3, "minute", 5} hour, minute = get_time() and: result = get_time() hour = result['hour'] minute = results["minute"] wouldn't break, now would: time_dict = dict(get_time()) Anyway, we need dataclasses AND NamedTuples because dataclasses down't behave like a tuple -- but that doesn't mean that they couldn't behave more like a dict in some ways. > And my toy code actually adds another decorator to make dataclasses > iterable, so it would be a completely optional feature. > > > That approach of adding support for iterability makes sense to me. I’m > contemplating adding a “dataclasses_tools” package for some other tools I > have. > I like that -- good idea. If any of my toy code is useful, please feel free to make use of it. > But I’m not sure how this fits in to the asdict discussion. > Well, it fits in in the sense that the question at hand is: Is there a need for a standard protocol for making dicts out of arbitrary classes? datacalsses were used as an example use-case, as datacalsses do naturally map to dicts. My point is that there are already two protocols for making an arbitrary classes into a dict, so I don't think we need another one. Even though those two are overloading other use cases: the Mapping ABC and iteration. This does mean that there would be no way to shoehorn NamedTuples into this -- as they already use the iteration protocol in a way that is incompatible with dict creation. So yeah, maybe a use case there. But the other option is to use a convention, rather than an official protocol -- if an object has an "asdict()" method, then that method returns a dict. pretty simple. If you were dealing with arbitrary objects, you'd have to write code like: try: a_dict = an_object.asdict() except (AttributeError, Type Error): a_dict = something_else but you'd need to do that anyway, as you couldn't count on every type being conformant with the dict() constructor anyway. So I'm still trying to see the use cases for having wanting to turn arbitrary objects into dicts. As for NamedTuple -- it does have _asdict: In [122]: p._asdict() Out[122]: OrderedDict([('x', 4), ('y', 5)]) (sidenote --now that dicts preserve order, maybe NamedTuple could return a regular dict) So I see the OP's point -- and it's a leading dunder name because: """ To prevent conflicts with field names, the method and attribute names start with an underscore. """ which I suppose means that if there is an informal protocol, it should also use that leading underscore. -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/