Imagine I have two dataclasses:
class A:
x: int
y: int
class B:
x:int
y:int
And I have a list of class a:
a_list = [A(x=1, y=2), A(x=3,y=4), ...]
What would be an elegant way of creating a list of class B from this list (copying the properties over in each case)?
CodePudding user response:
Give B
a class method that produces an instance of B
given an instance of A
:
class B
x: int
y: int
@classmethod
def from_A(cls, a):
return cls(a.x, a.y)
Then you can write
bs = [B.from_A(a) for a in a_list]
There's a bit of an asymmetry here: B
knows details about A
, but A
knows nothing about B
. You could reverse this and let instances of A
produce instances of B
:
class A:
x: int
y: int
def to_B(self):
return B(self.x, self.y)
bs = [a.to_B() for a in a_list]
Or, you could decide that neither A
nor B
should be "privileged" to know details about the other, instead having a third "omniscient" entity that knows how to go in one direction or the other. (This is at least symmetrical.)
def b_from_a(a):
return B(a.x, a.y)
bs = [b_from_a(a) for a in a_list]
How you decide to encapsulate the creation of a B
from an A
is up to you; other factors in your code may help you decide which of the three options is most reasonable.
CodePudding user response:
Assuming both are dataclasses and all of the names match up, you can pass A
as keyword arguments to B
's constructor using asdict
.
my_b_object = B(**asdict(my_a_object))
and, of course, to apply it over a list, use a list comprehension.
b_list = [B(**asdict(a)) for a in a_list]
CodePudding user response:
Access the attributes directly and feed them into B
:
b_list = [B(a.x, a.y) for a in a_list]