Supposons que vous ayez défini une classe de données Python:
marker_a = Marker(1.0, 2.0) marker_b = Marker(11.0, 12.0) # now some magic happens which you hopefully can fill in print(marker_b) # result: Marker(a=1.0, b=2.0)
Quelle est la manière la plus simple de copier les valeurs d'une instance marker_a
vers une autre instance marker_b
?
Voici un exemple de ce que j'essaye d'accomplir:
@dataclass class Marker: a: float b: float = 1.0
En tant que condition aux limites, je ne veux pas créer et affecter une nouvelle instance à marker_b
. OK, je pourrais parcourir tous les champs définis et copier les valeurs une par une, mais il doit y avoir un moyen plus simple, je suppose.
4 Réponses :
marker_a = Marker(1.0, 2.0) marker_b = Marker(11.0, 12.0) marker_b.__dict__ = marker_a.__dict__.copy() # result: Marker(a=1.0, b=2.0)
Je pense que faire une boucle sur les champs est probablement le moyen le plus simple. Toutes les autres options auxquelles je peux penser impliquent la création d'un nouvel objet.
from dataclasses import fields marker_a = Marker(5) marker_b = Marker(0, 99) for field in fields(Marker): setattr(marker_b, field.name, getattr(marker_a, field.name)) print(marker_b) # Marker(a=5, b=1.0)
Merci. C'est similaire à ce que je fais en ce moment, mais cela ne me semble pas pythonique.
C'est un cas d'utilisation un peu inhabituel. Le module dataclasses semble principalement supposer que vous serez heureux de créer un nouvel objet. Je recommanderais de coller ceci (ou ce que vous avez) dans une fonction et de passer à autre chose. Une chose à laquelle il convient de réfléchir est ce que vous voulez faire si l'un de vos arguments est en fait une sous-classe de Marker
avec des champs supplémentaires.
La fonction dataclasses.replace
renvoie une nouvelle copie de l'objet. Sans transmettre aucun changement, il renverra une copie sans modification:
>>> import dataclasses >>> @dataclasses.dataclass ... class Dummy: ... foo: int ... bar: int ... >>> dummy = Dummy(1, 2) >>> dummy_copy = dataclasses.replace(dummy) >>> dummy_copy.foo = 5 >>> dummy Dummy(foo=1, bar=2) >>> dummy_copy Dummy(foo=5, bar=2)
Notez qu'il s'agit d'une copie superficielle.
Une autre option qui peut être plus élégante:
import dataclasses marker_a = Marker(1.0, 2.0) marker_b = Marker(**dataclasses.asdict(marker_a))
Merci, mais ma condition limite était de ne pas créer une nouvelle instance. Dans mon cas particulier, un autre objet pointe vers cette instance particulière, donc une nouvelle instance n'est pas une option.