Use str.format() to access object attributes
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.
Related videos on Youtube
Comments
-
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 over 9 yearsThis looks better to me:
print 'My object has strings a={obj.a}, b={obj.b}, c={obj.c}'.format(obj=obj)
-
Adam Hughes over 9 yearsAwesome guys, thanks. Does the "0." (e.g. 0.a) denote the index of the item passed to format?
-
Admin over 9 years@AdamHughes - Exactly. Python begins numbering at
0
just like C/C++.0
is the first (only) argument tostr.format
. -
Admin over 9 years@RomanL - The OP disliked his current solution because it required you to type
obj
once per attribute. Writingobj
that many times is tedious and unnecessary IMO. But, as you said, it is mainly a matter of preference. :) -
Adam Hughes over 9 yearsThat's right, but I still appreciate seeing the alternative approaches. I was unaware of both cases!
-
Roman L over 9 years@iCodez:
0
andobj
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 than0.a
IMO. -
igniteflow almost 9 yearsAlso
'{a} {b}'.format(**vars(obj))
or'{a} {b}'.format(**obj.__dict__)
-
Halcyon Abraham Ramirez almost 9 years@iCodez can you this to access class methods as well? or just class attributes?
-
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 over 8 yearsNice! 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 over 4 yearsif you define
__slots__
there is no__dict__
, thenvars
wouldn't work at all.