Reputation: 375565
Python has a great way to do string substitutions with a dictionary.
How can I replicate this same behaviour in my own object (rather than use a dictionary)?
In [1]: d = {'hello': 'world'}
In [2]: '%(hello)s' % d
Out[2]: 'world'
For example, if I have a class MyClass
:
In [3]: class MyClass():
a = 'x'
b = 'y'
In [4]: m = MyClass()
Without any mapping, we expect string substitution to throw an error (and they do), but suppose I want it to act like {'a' : 'x'}
i.e. have the following return 'x'
:
In [5]: '%(a)s' % m
TypeError: format requires a mapping
I've been messing around with format string syntax (__format__
) or template string, without success.
How can I provide my class a "mapping" (dictionary?) to use in string substitution?
Upvotes: 1
Views: 375
Reputation: 1122282
Your MyClass()
instances do have a dictionary associated with them, access it with the vars()
function:
'%(a)s' % vars(m)
This works for all custom classes that do not use a __slots__
attribute.
Alternatively, you can use the newer ''.format()
string formatting method, which lets you access object attributes:
'{0.a}'.format(m)
It's this method of formatting that looks for a .__format__(format_spec)
method on your custom classes, see the format()
function documentation.
Last but not least, any object with a .__getitem__()
method can be used for string formatting as if it is a dictionary:
>>> class Foo(object):
... def __getitem__(self, name):
... if name == 'bar': return 'baz'
... raise AttributeError(name)
...
>>> '%(bar)s' % Foo()
'baz'
Upvotes: 3