Add `iter=True` to dataclass decorator

Thanks all for the replies!

The downside I see to namedtuple is that you need to be comfortable buying into the object being an actual tuple. I often don’t want many of the features that tuples provide:

>>> from typing import NamedTuple
>>> class Point(NamedTuple):
...     x: float
...     y: float
...
>>> p = Point(1, 2)
>>> q = Point(3, 4)
>>> p + q
(1, 2, 3, 4)
>>> p * 2
(1, 2, 1, 2)
>>> len(p)
3

As others have noted, using astuple isn’t quite right and I didn’t use it in my linked example code and probably should have noted its downsides in my initial post.

As @peterc noted, the astuple function deeply copies (which is unnecessary for this use case). But even weirder it deeply converts all dataclasses to tuples, as @DavidCEllis noted.

>>> from dataclasses import astuple, dataclass
>>>
>>> @dataclass
... class A:
...     n: float
...     m: float
...
>>> @dataclass
... class B:
...     a: A
...     x: float
...     y: float
...     def __iter__(self):
...         return iter(astuple(self))
...
>>> b = B(a=A(1, 2), x=3, y=4)
>>> list(b)
[(1, 2), 3, 4]

The way to implement __iter__ correctly might look like this:

    def __iter__(self):
        for field in dataclasses.fields(cls):
            yield getattr(self, field.name)

If there was a less verbose way to correctly implement this, I wouldn’t be so tempted to propose adding iter=True to dataclasses.dataclass.

1 Like