ericvsmith / dataclasses

Apache License 2.0
584 stars 53 forks source link

How to define a dataclass so each of its attributes is the list of its subclass attributes? #163

Closed lhoupert closed 3 years ago

lhoupert commented 3 years ago

Hi all, I was wondering if I missed this functionality or if it doesn't exist?

For example, I have this code:

from dataclasses import dataclass
from typing import List

@dataclass
class Position:
    name: str
    lon: float
    lat: float

@dataclass
class Section:
    positions: List[Position]

pos1 = Position('a', 52, 10)
pos2 = Position('b', 46, -10)
pos3 = Position('c', 45, -10)

sec = Section([pos1, pos2 , pos3])

How can I create additional attributes in the dataclass Section so they would be a list of the attribute of its subclass Position?

In my example, I would like that the section object also returns:

sec.names = ['a', 'b', 'c']   #[pos1.name,pos2.name,pos3.name]
sec.lons = [52, 46, 45]       #[pos1.lon,pos2.lon,pos3.lon]
sec.lats = [10, -10, -10]     #[pos1.lat,pos2.lat,pos3.lat]

I was hoping to find a solution such as:

@dataclass
class Section:
    positions: List[Position]
    names :  List[Position.name]

But of course, it is not working because name is not an attribute of position. I can define the object attributed later in the code (e.g. by doing secs.name = [x.name for x in section.positions]). But it would be nicer if it can be done at the dataclass definition level. Is it possible to do that?

Thank you,

Loïc

ericvsmith commented 3 years ago

You could declare the names attribute as having a default value of None (or really anything), then initialize them in __post_init__. That will only help you at __init__-time, though. There's no way to keep them in sync if positions is subsequently modified.

But why not just write a member function that returns what you want? I don't think these need to be fields of a dataclass.

I'm going to close this, since this repo is only for the 3.6 backport of dataclasses, which I'm not really supporting any more. You should probably ask this question on Stack Overflow or python-list for better answers.