Comment créer une nouvelle inconnue ou dynamique/expando objet en Python
En python comment pouvons-nous créer un nouvel objet sans avoir une Classe prédéfinie et, plus tard, ajouter dynamiquement des propriétés ?
exemple:
dynamic_object = Dynamic()
dynamic_object.dynamic_property_a = "abc"
dynamic_object.dynamic_property_b = "abcdefg"
Quelle est la meilleure façon de le faire?
MODIFIER Parce que beaucoup de personnes conseillé dans les commentaires que je ne pourrais pas besoin de cela.
Le truc c'est que j'ai une fonction qui sérialise les propriétés d'un objet. Pour cette raison, je ne veux pas créer un objet de la classe en raison de certaines constructeur de restrictions, mais au lieu de créer un poste similaire, disons comme un se moquer de, ajouter les propriétés de "custom" j'ai besoin, puis le nourrir à la fonction.
- Qu'est ce qu'une propriété dynamique"? comme dans
setattr(dynamic_object, variable_with_property_name, variable_with_property_value)
? vous avez besoin d'un collection pour associer des propriétés à des valeurs, et le "type" de cette chose est utilisé dans un endroit... pourriez-vous peut-être voulez vraiment undict
? - vérifier la mise à jour de question
InformationsquelleAutor Jimmy Kane | 2012-12-23
Vous devez vous connecter pour publier un commentaire.
Il suffit de définir votre propre classe pour le faire:
namedtuple
classe à la place.À l'aide d'un objet à conserver des valeurs n'est pas le plus Pythonic style de programmation. Il est commun dans les langages de programmation qui ne sont pas de bonne conteneurs associatifs, mais en Python, vous pouvez utiliser un dictionnaire:
Vous pouvez également utiliser un "dictionnaire littérale" pour définir le contenu du dictionnaire tout à la fois:
Ou, si vos clés sont tous des identificateurs (et ils le seront, si vous prévoyez d'entre eux étant des noms d'attribut), vous pouvez utiliser le
dict
constructeur avec mot-clé les arguments comme des paires clé-valeur:Remplir un dictionnaire est en fait ce que Python est fait en arrière-plan lorsque vous utilisez un objet, comme dans Ned Batchelder de réponse. Les attributs de son
ex
objet sont stockés dans un dictionnaire,ex.__dict__
, qui doit être égale à l'équivalentdict
créé directement.À moins que la syntaxe d'attribut (par exemple,
ex.foo
) est absolument nécessaire, vous pouvez ignorer l'objet et utiliser directement un dictionnaire.object()
.dict
s, ce qui était mon principal suggestion.collections.namedtuple
fabrique de classe..Si vous prenez metaclassing approche de @Martijn réponse, @Nie la réponse peut être réécrit de la plus courte (même si c'est évidemment moins lisible, mais la même chose).
Ou tout simplement, qui fait la même chose que ci-dessus en utilisant
dict
argument:Pour Python 3, passage de l'objet à
bases
argument n'est pas nécessaire (voirtype
documentation).Mais pour les cas simples de l'instanciation de ne pas avoir un avantage, donc c'est normal de le faire:
Dans le même temps, personnellement, je préfère une plaine de classe (c'est à dire sans instanciation) pour ad-hoc test de la configuration des cas comme la plus simple et lisible:
Mise à jour
En Python 3.3,+, il est exactement ce que l'OP demande,
types.SimpleNamespace
. C'est juste:Cependant, dans stdlib de Python 2 et Python 3 il y a
argparse.Espace de noms
, qui a le même but:Noter que les deux peuvent être initialisés avec le mot-clé arguments:
Utiliser le
collections.namedtuple()
de la fabrique de classe pour créer une classe personnalisée pour votre valeur de retour:La valeur retournée peut être utilisé à la fois comme un n-uplet et par attribut d'accès:
Une façon que j'ai trouvé est également par la création d'un lambda. Il peut avoir des effets secondaires et est livré avec des propriétés qui ne sont pas voulu. Seulement l'affichage de l'intérêt.
dynamic_object.__name__
)