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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.