4

TypeScript has a Pick type which can take an existing type and create a new one by picking individual attributes. I would like to have a similar functionality in Python, so for example:

from dataclasses import dataclass
from pick import Pick

@dataclasses.dataclass
class Foo:
    x: int
    y: float
    z: str

Bar = Pick(Foo, ('x', 'y'))

foo = Foo(1, 2.0, '3')
bar = Bar(1, 2.0)

I want this to avoid the problem of partial object population without having to explicitly define many different classes which are really just subsets of a larger one. Ideally, this will be type-safe and recognized by mypy.

I looked at other solutions like defining a new class for every subset of attributes, but that produced too many classes which are all similar but just slightly different, making the code harder to read. I also tried having a large class with every field being optional, but that still makes the code hard to read because I have to reason about the lineage of an object to tell whether it will have some field, or if that field is null.

Bonus points if there is also a way to add a field via something like Baz = Add(Foo, {'w': List}); baz(1, 2.0, '3', w=[])

Cory Nezin
  • 51
  • 2
  • There is not. How would `Bar` be defined? Would it have the same methods as `Foo`? What would those methods do if they depended on `z`? `Pick`, I believe, operates on something simpler than Python classes. – chepner Jan 19 '23 at 17:28
  • 1
    Adding a field is easier: just use inheritance. – chepner Jan 19 '23 at 17:29
  • @chepner good point, I don't need it to work for a general class, I would be fine with it being constrained to some special subset of classes. I don't really know TypeScript so I'm not sure what the difference is there. – Cory Nezin Jan 19 '23 at 17:34
  • As far as I know, the things `Pick` operate on are *just* types, with no associated methods. `Pick` doesn't do much more than build a new type from scratch, using the types used by `Foo` to set the types used by `Bar`. – chepner Jan 19 '23 at 17:40
  • The classes may be similar, but if they serve different *needs*, they *should* be separate classes. But needing so many similar classes may indicate a larger design problem to be fixed, not worked around. – chepner Jan 19 '23 at 17:49
  • The main issue is I am keeping track of objects which have a huge number of attributes, but my functions generally only need a small number of those attributes for a given function. I don't want to load a bunch of attributes that I don't need. – Cory Nezin Jan 19 '23 at 17:59
  • You probably shouldn't *have* objects with a huge number of attributes. Break it down into a collections of simpler objects, where each of your function really only needs on one of the simpler objects. – chepner Jan 19 '23 at 18:02

0 Answers0