Je veux créer un objet dynamique (à l'intérieur d'un autre objet) en Python, puis y ajouter des attributs.
J'ai essayé:
obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')
mais cela n'a pas fonctionné.
Des idées?
Éditer:
Je mets les attributs d'une for
boucle qui boucle à travers une liste de valeurs, par exemple
params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()
for p in params:
obj.a.p # where p comes from for loop variable
Dans l'exemple ci - dessus , je recevrais obj.a.attr1
, obj.a.attr2
, obj.a.attr3
.
J'ai utilisé la setattr
fonction parce que je ne savais pas comment faire à obj.a.NAME
partir d'une for
boucle.
Comment définirais-je l'attribut en fonction de la valeur de p
dans l'exemple ci-dessus?
python
class
object
attributes
John
la source
la source
a = object()
et vous en avez besoinobj.a = object()
. Encore une fois, je parle de l'exemple, dans votre code réel, un objet à l'intérieur d'un objet peut être utile.Réponses:
Vous pouvez utiliser mon ancienne recette de Bunch , mais si vous ne voulez pas créer une "classe de bunch", une très simple existe déjà en Python - toutes les fonctions peuvent avoir des attributs arbitraires (y compris les fonctions lambda). Ainsi, les travaux suivants:
Que la perte de clarté par rapport à la vénérable
Bunch
recette soit correcte, c'est une décision de style que je vous laisse bien sûr.la source
lambda: 23
), de sorte que ces experts utilisentlambda
s à cette fin se sentirait probablement rien comme "un hack". Personnellement, je n'aime pas beaucouplambda
en Python - mais c'est vraiment une question de goût personnel.lambda
modèle convient à votre cas d'utilisation peut vous amener à réaliser que quelque chose que vous aviez initialement pensé comme des données est en fait plus une fonction - ou, en tout cas, un foncteur.from argparse import Namespace
je préférerais peut-être que je vive ailleurs *, par exemplecollection
) - en réutilisant à nouveau un type existant, juste meilleur, et en évitant toujours la création de nouveaux types. Mais ce n'était pas là alors :-).L'intégré
object
peut être instancié mais aucun attribut ne peut y être défini. (Je souhaite que ce soit possible, dans ce but précis.) Il n'a pas__dict__
de support pour les attributs.Je fais généralement juste ceci:
Quand je le peux, je donne à la
Object
classe un nom plus significatif, selon le type de données que j'y mets.Certaines personnes font une chose différente, où elles utilisent une sous-classe
dict
qui permet l'accès aux attributs pour obtenir les clés. (d.key
au lieu ded['key']
)Edit : Pour l'ajout à votre question, l'utilisation
setattr
est très bien. Vous ne pouvez tout simplement pas utilisersetattr
sur lesobject()
instances.la source
foo = object()
fonctionne, mais vous ne pouvez pas faire grand-chose avec luitype....
ou lambda n'a jamais été mon préféré, comme du vomi de texte dans mon code. Mais cette idée est idéale pour utiliser des objets pour conserver des propriétés. Laisse le code plus lisible b / c quand je vois lambda je ralentis ma lecture à 25% alors que votre chemin est totalement logique! Merci.Struct
le nom de la classe pour la rendre plus évidente. M'a sauvé une tonne de dactylographie["
et"]
, Cheers!Il y a de la
types.SimpleNamespace
classe dans Python 3.3+ :collections.namedtuple
,typing.NamedTuple
pourrait être utilisé pour des objets immuables. PEP 557 - Les classes de données suggèrent une alternative mutable.Pour une fonctionnalité plus riche, vous pouvez essayer le
attrs
package . Voir un exemple d'utilisation .la source
argparse.Namespace
classeattrs
package @Roel prend en charge Python 2.7Il existe plusieurs façons d'atteindre cet objectif. Fondamentalement, vous avez besoin d'un objet extensible.
la source
obj.a = type('', (), {})
Le
mock
module est essentiellement conçu pour cela.la source
unittest.Mock
fait partie de la bibliothèque standard depuis Python 3.3 ( docs.python.org/3/library/unittest.mock.html )mock
. Je me sens juste bizarre.Maintenant, vous pouvez le faire (je ne sais pas si c'est la même réponse que evilpie):
la source
Essayez le code ci-dessous:
la source
Vous pouvez également utiliser directement un objet de classe; il crée un espace de noms:
la source
comme le disent les docs :
Vous pouvez simplement utiliser une instance de classe factice.
la source
Ces solutions sont très utiles lors des tests. En s'appuyant sur les réponses de tous les autres, je le fais en Python 2.7.9 (sans méthode statique, j'obtiens une TypeError (méthode non liée ...):
la source
Quels objets utilisez-vous? Je viens d'essayer cela avec un exemple de classe et cela a bien fonctionné:
Et j'ai eu
123
comme réponse.La seule situation où je vois cet échec est si vous essayez un
setattr
sur un objet intégré.Mise à jour: Du commentaire, il s'agit d'une répétition de: Pourquoi ne pouvez-vous pas ajouter d'attributs à un objet en python?
la source
J'y arrive tard dans la journée, mais voici mon pennyworth avec un objet qui se trouve justement contenir des chemins utiles dans une application, mais vous pouvez l'adapter à tout ce que vous voulez un sorta dict d'informations que vous pouvez accéder avec getattr et notation par points (c'est à quoi je pense que cette question concerne vraiment):
C'est cool parce que maintenant:
Donc, cela utilise l'objet fonction comme les réponses ci-dessus mais utilise la fonction pour obtenir les valeurs (vous pouvez toujours utiliser
(getattr, x_path, 'repository')
plutôt quex_path('repository')
si vous préférez).la source
Si nous pouvons déterminer et agréger tous les attributs et valeurs ensemble avant de créer l'objet imbriqué, alors nous pourrions créer une nouvelle classe qui prend un argument de dictionnaire lors de la création.
Nous pouvons également autoriser les arguments de mots clés. Voir cet article .
la source
la source
Autre façon je vois, de cette façon:
la source
class a: pass
donne toute la puissance requise.