Use str.format() to access object attributes

25,260

Solution 1

You can use the .attribute_name notation inside the format fields themselves:

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

Below is a demonstration:

>>> 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'
>>>

Note however that you do need to number the format fields when doing this. Also, as you can see, the str.format function has its format fields denoted by curly braces {...}, not the % sign.

For more information, here is a reference on the Format String Syntax in Python.

Solution 2

I think it's preferable to use vars() to access an object's attributes as a dict rather than usng __dict__.

So you could do this:

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

For more background on why vars() is preferable to __dict__, see the answer to the question Use dict or vars()?.

Solution 3

As @igniteflow wrote in a buried comment:

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

With my limited python understanding: .__dict__ is a dict with all the instances attributes and the ** operator basically unpacks them and adds them as key=value args to the method

Solution 4

For the sake of completeness, building on @igniteflow and @Christian, you could use the % string format operator and write:

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

Solution 5

Some of the suggested answers that rely on vars(...) don't work with immutable objects:

>>> 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'

I think it's preferable to stick with something reliable and explicitly list what you need to be printed.

If you need to print a ton of attributes then storing those values as attributes might not be the best idea.

Share:
25,260

Related videos on Youtube

Adam Hughes
Author by

Adam Hughes

Software developer and Physics PhD

Updated on July 09, 2022

Comments

  • Adam Hughes
    Adam Hughes almost 2 years

    I have a Python object with attributes a, b, c.

    I still use old string formatting, so I'd normally print these manually:

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

    Lately, my strings have been getting super long, and I'd much rather be able to simply pass the object into a string format function, something like:

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

    However, the syntax is incorrect. Is this possible?

  • Roman L
    Roman L over 9 years
    This looks better to me: print 'My object has strings a={obj.a}, b={obj.b}, c={obj.c}'.format(obj=obj)
  • Adam Hughes
    Adam Hughes over 9 years
    Awesome guys, thanks. Does the "0." (e.g. 0.a) denote the index of the item passed to format?
  • Admin
    Admin over 9 years
    @AdamHughes - Exactly. Python begins numbering at 0 just like C/C++. 0 is the first (only) argument to str.format.
  • Admin
    Admin over 9 years
    @RomanL - The OP disliked his current solution because it required you to type obj once per attribute. Writing obj that many times is tedious and unnecessary IMO. But, as you said, it is mainly a matter of preference. :)
  • Adam Hughes
    Adam Hughes over 9 years
    That's right, but I still appreciate seeing the alternative approaches. I was unaware of both cases!
  • Roman L
    Roman L over 9 years
    @iCodez: 0 and obj are repeated the same number of times within the string. A realistic example with a shortened obj: 'a={o.a}, b={o.b}'.format(o=my_actual_object_name). To someone not familiar with this notation this is much more obvious than 0.a IMO.
  • igniteflow
    igniteflow almost 9 years
    Also '{a} {b}'.format(**vars(obj)) or '{a} {b}'.format(**obj.__dict__)
  • Halcyon Abraham Ramirez
    Halcyon Abraham Ramirez almost 9 years
    @iCodez can you this to access class methods as well? or just class attributes?
  • Admin
    Admin over 8 years
    @HalcyonAbrahamRamirez - You can access methods, yes, but you will not be able to call them. Instead, you will get a string representation of the method like: <bound method Class.method of <__main__.Class object at 0x0000000002CC27B8>>'.
  • pythonjsgeo
    pythonjsgeo over 8 years
    Nice! Using '**' is the key. Including .__dict__ in the example is unfortunate because it makes it look more complicated than it is. e.g. 'My object has strings a={a}, b={b}'.format(**{'a':'hi', 'b':'mom'})
  • Shiplu Mokaddim
    Shiplu Mokaddim over 4 years
    if you define __slots__ there is no __dict__, then vars wouldn't work at all.