Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save malcolmgreaves/b42491da7c051c6f635275107473858f to your computer and use it in GitHub Desktop.
Save malcolmgreaves/b42491da7c051c6f635275107473858f to your computer and use it in GitHub Desktop.
Adds syntactic support to destructing an @DataClass into field-values the same way a NamedTuple (or tuple) is.
from abc import ABC
from typing import Any, Iterable, Tuple
from dataclasses import dataclass
from functools import partial
@dataclass
class TupleDestructureSyntax(ABC):
"""Allows any @dataclass class to be decomposed into its fields & values as if it were a tuple.
For example, if a `@dataclass` `X` has three fields:
@dataclass class X:
a: int
b: str
c: float
Then, given an instance `x`, it can be destructured into its components using the same syntax
that applies to tuples (and thuss `NamedTuple`-extending classes) as:
x: X = ...
a, b, c = x
"""
def __iter__(self) -> Iterable[Tuple[Any, ...]]:
return iter(tuple(map(partial(getattr, self), self.__dataclass_fields__.keys())))
# runnable example produces this output:
# >>>
# z=Z(name='bob', money=3.51, age=42)
# Z=<class '__main__.Z'>
# name='bob'
# money=3.51
# age=42
# the 2nd example class shows that inheritence still works:
# >>>
# a=A(name='jane', money=9999., age=3, location='earth')
# name='jane'
# money=9999.0
# age=3
# location='earth'
@dataclass(frozen=True)
class Z(TupleDestructureSyntax):
name: str
money: float
age: int
z = Z("bob", 3.51, 42)
print(f"{z=}")
print(f"{Z=}")
name, money, age = z
print(f"{name=}")
print(f"{money=}")
print(f"{age=}")
@dataclass(frozen=True)
class A(Z):
location: str
a = A('jane', 9999., 3, "earth")
print(f"{a=}")
name, money, age, location = a
print(f"{name=}")
print(f"{money=}")
print(f"{age=}")
print(f"{location=}")
@malcolmgreaves
Copy link
Author

malcolmgreaves commented Jun 20, 2023

Running this example produces:

z=Z(name='bob', money=3.51, age=42)
Z=<class '__main__.Z'>
name='bob'
money=3.51
age=42
a=A(name='jane', money=9999.0, age=3, location='earth')
name='jane'
money=9999
age=3
location='earth'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment