web-dev-qa-db-fra.com

Utilisez str.format () pour accéder aux attributs d'objet

J'ai un objet Python avec les attributs a, b, c.

J'utilise toujours l'ancien formatage des chaînes, donc je les imprimerais normalement manuellement:

 print 'My object has strings a=%s, b=%s, c=%s' % (obj.a, obj.b, obj.c)

Dernièrement, mes chaînes sont devenues très longues et je préférerais de beaucoup pouvoir simplement passer l'objet dans une fonction de format de chaîne, quelque chose comme:

 print 'My object has strings a=%a, b=%b, c=%c'.format(obj)

Cependant, la syntaxe est incorrecte. Est-ce possible?

27
Adam Hughes

Vous pouvez utiliser la notation .attribute_name à l'intérieur des champs de format eux-mêmes:

print 'My object has strings a={0.a}, b={0.b}, c={0.c}'.format(obj)

Ci-dessous une démonstration:

>>> class Test(object):
...     def __init__(self, a, b, c):
...         self.a = a
...         self.b = b
...         self.c = c
...
>>> obj = Test(1, 2, 3)
>>> 'My object has strings a={0.a}, b={0.b}, c={0.c}'.format(obj)
'My object has strings a=1, b=2, c=3'
>>>

Notez cependant que vous devez numéroter les champs de format pour cela. En outre, comme vous pouvez le constater, la fonction str.format a ses champs de format désignés par des accolades {...}, pas le signe %.

Pour plus d'informations, voici une référence sur Format String Syntax in Python.

44
iCodez

Je pense qu'il est préférable d'utiliser vars () pour accéder aux attributs d'un objet en tant que dict plutôt que d'utiliser __dict__.

Pour que vous puissiez faire ceci:

"My object has strings a={a}, b={b}, c={c}".format(**vars(obj))

Pour plus d'informations sur les raisons pour lesquelles vars() est préférable à __dict__, voir la réponse à la question Utilisez dict ou vars ()? .

11
Geoffrey Hing

Comme @igniteflow a écrit dans un commentaire enfoui:

'My object has strings a={a}, b={b}, c={c}'.format(**obj.__dict__)

Avec ma compréhension limitée de python: .__dict__ est un dict avec tous les attributs d'instances et l'opérateur ** les décompresse et les ajoute en tant qu'arguments key = value à la méthode.

5
Christian

Par souci d'exhaustivité, en vous basant sur @igniteflow et @Christian, vous pouvez utiliser l'opérateur de formatage de chaîne % et écrire:

'My object has strings a=%(a)s, b=%(b)s, c=%(c)s' % obj.__dict__
1
Jason

Certaines des réponses suggérées qui s'appuient sur vars(...) ne fonctionnent pas avec des objets immuables:

>>> class foo(object):
...   __slots__ = ()
...   def __init__(self):
...     self.x = 1
...
>>> vars(foo())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
AttributeError: 'foo' object has no attribute 'x'

Je pense qu'il est préférable de s'en tenir à quelque chose de fiable et de lister explicitement ce que vous devez imprimer.

Si vous devez imprimer une tonne d'attributs, stocker ces valeurs sous forme d'attributs n'est peut-être pas la meilleure idée.

0
iggy