I want to format a string and be able to use the dot operator, so that I can construct template strings containing e.g. {user.name}
, {product.price}
.
I tried this:
'Hello {user.name}'.format( {'user': { 'name': 'Markus' } } )
KeyError: 'user'
'Hello {user.name}'.format( **{'user': { 'name': 'Markus' } } )
AttributeError: 'dict' object has no attribute 'name'
Is there a way to do it?
2f means to round up to two decimal places. You can play around with the code to see what happens as you change the number in the formatter.
Strings are objects in Python which means that there is a set of built-in functions that you can use to manipulate strings. You use dot-notation to invoke the functions on a string object such as sentence.
Python dict
objects are unfortunately not attribute accessible (i.e. with the dot notation) by default. So you can either resign yourself to the uglier brackets notation:
'Hello {user[name]}'.format( **{'user': { 'name': 'Markus' } } )
Or you can wrap your data in a dot-accessible object. There are a handful of attribute-accessible dictionary classes you can install from PyPI, such as stuf.
from stuf import stuf
'Hello {user.name}'.format( **stuf({'user': { 'name': 'Markus' } }) )
I tend to keep my collections in stuf
objects so that I can easily access them by attribute.
The minimal change is to use square brackets in your template, rather than a period:
# v Note
>>> 'Hello {user[name]}'.format(**{'user': {'name': 'Markus'}})
'Hello Markus'
Alternatively, put objects that actually have that attribute in the dictionary, e.g. a custom class or collections.namedtuple
:
>>> class User(object):
def __init__(self, name):
self.name = name
>>> 'Hello {user.name}'.format(**{'user': User('Markus')})
'Hello Markus'
Note also that if you're writing out the literal you can just use a keyword argument:
>>> 'Hello {user.name}'.format(user=User('Markus'))
'Hello Markus'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With