Imagine I have an object which is an instance of a class such as the following:
@dataclass
class Foo:
bar: int
baz: str
I'm using dataclasses for convenience, but in the context of this question, there is no requirement that the class be a dataclass.
Normally, if I want to unpack the attributes of such an object, I must implement __iter__, e.g. as follows:
class Foo:
...
def __iter__(self) -> Iterator[Any]:
return iter(dataclasses.astuple(self))
bar, baz = Foo(1, "qux")
However, from the perspective of a static type checker like pyright, I've now lost any type information for bar and baz, which it can only infer are of type Any. I could improve slightly by creating the iter tuple parameter manually:
def __iter__(self) -> Iterator[Union[str, int]]:
return iter((self.bar, self.baz))
But I still don't have specific types for bar and baz. I can annotate bar and baz and then use dataclasses.astuple directly as follows:
bar: str
baz: int
bar, baz = dataclasses.astuple(Foo(1, "qux"))
but that necessitates less readable multi-level list comprehensions such as
bars: list[int] = [
bar for bar, _ in [dataclasses.astuple(foo) for foo in [(Foo(1, "qux"))]]
]
and also ties me to dataclasses.
Obviously, none of this is insurmountable. If I want to use a type checker, I can just not use the unpack syntax, but I would really like to if there's a clean way to do it.
An answer that is specific to dataclasses, or better yet, attrs, is acceptable if a general method is not currently possible.