15

Say I've got a dictionary with dots in the name of fields, like {'person.name': 'Joe'}. If I wanted to use this in str.format, is it possible?

My first instinct was

'Name: {person.name}'.format(**{'person.name': 'Joe'})

but this would only work if my dict were shaped like

{'person':{'name':Joe}}

The relevant manual docs section doesn't mention anyway of escaping the dot.

(Sidenote: I thought that generally

def func(**kw): print(kw)
func(**{'a.b': 'Joe'})

would cause an error, but the **-expanded function call seems to work even if they're not valid identifiers! It does error out on non-strings though. o_O)

3
  • Have you tried escaping the dot with a backslash? Commented Oct 28, 2011 at 20:35
  • @RafeKettler: Yes. That doesn't work because you're escaping it for the string, not the format specifier. Commented Oct 29, 2011 at 6:18
  • Possible duplicate of How to use a dot in Python format strings? Commented Sep 18, 2016 at 7:59

4 Answers 4

8
'Name: {0[person.name]}'.format({'person.name': 'Joe'})
Sign up to request clarification or add additional context in comments.

4 Comments

Close but that would only work if you're passing a dictionary with a single key, one for each positional replacement. For example this would fail: 'Name: {0[person.name]} Age: {1[person.age]}'.format({'person.name': 'Joe', 'person.age': 42})
But you can repeat 0 as many times as is necessary. This works fine: 'Name: {0[person.name]} Age: {0[person.age]}'.format({'person.name': 'Joe', 'person.age': 42})
Awesome, I was not aware you could do that and I have learned something. Thanks! :)
Note that since 2.7 you can omit the integer indices if it's just the same order as in the string: 'Name: {[person.name]}'.format({'person.name': 'Joe'}) yields 'Name: Joe'. It would still require reusing 0 for subsequent access. My only problem is that it's kind of ugly. I guess I could just mangle it to 'person_age' if I needed to make sure.
7

I had similar issue and I solved it by inheriting from string.Formatter:

import string

class MyFormatter(string.Formatter):
    def get_field(self, field_name, args, kwargs):
        return (self.get_value(field_name, args, kwargs), field_name)

however you can't use str.format() because it's still pointing to old formatter and you need to go like this

>>> MyFormatter().vformat("{a.b}", [], {'a.b': 'Success!'})
'Success!'

Comments

5

One way to work around this is to use the old % formatting (which has not been deprecated yet):

>>> print 'Name: %(person.name)s' % {'person.name': 'Joe'}
Name: Joe

Comments

0

f-strings handle this cleanly (I realize they were not available at the time of the original post):

>>> x = {'person.name': 'Joe'}
>>> print(f"Name: {x['person.name']}")
Name: Joe

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.