2016-03-29 2 views
2

Это простой Peasy:питон: defaultdict не работает с строкой форматирования

'foo {bar}'.format(**{'bar': 0}) 

Это не работает, получая KeyError:

from collections import defaultdict 
d = defaultdict(int) 
'foo {bar}'.format(**d) 

Есть ли способ для размещения defaultdict в форматирование строк?

+0

Аргументы ключевого слова передаются как словарь, а не 'defaultdict'. Я очень сомневаюсь, что есть простой способ. – zondo

+1

Это, похоже, работает в современном Python. Какую версию ты используешь? – DSM

+1

Сбой в 2.7.10 – NPE

ответ

6

** распаковка производит dict, поэтому это не работает. Если вы используете Python 3.2 или выше, хотя, вы можете пройти defaultdict без распаковки str.format_map, которая существует именно для целей прохождения Непро- типов dict отображения:

'foo {bar}'.format_map(d) 

Редактировать: По-видимому, в Python 3.5 по крайней мере, 'foo {bar}'.format(**d) на самом деле работать с defaultdict(int) и d изменяется (после форматирования repr является defaultdict(<class 'int'>, {'bar': 0})), так что это выглядит как в современном Python, format_map не может быть необходим для подклассов dict. Интересно.

+0

Черт, думаю, я застрял, когда использую 2.7.10. – Wells

1

Учитывая другой ответ и комментарий, по-видимому, что делает работы в Python3, но в python2 вам нужно сделать что-то немного больше хака:

from string import Formatter 
from collections import defaultdict 

mystring = 'foo {bar}' 
d = defaultdict(int) 
parts = Formatter().parse(mystring) 
newstring = mystring.format(**{part[1]: d[part[1]] for part in parts}) 
1

на основе @zondo's answer (и в малой степени , @ShadowRanger's), вы могли бы сделать что-то вроде этого, которое корректно работало как для Python 2.7.11, так и для 3.5.1.

from string import Formatter 
from collections import defaultdict 

def string_format_map(fmt, d): 
    try: 
     str.format_map 
    except AttributeError: 
     parts = Formatter().parse(fmt) 
     return fmt.format(**{part[1]: d[part[1]] for part in parts}) 
    else: 
     return fmt.format(**d) 

d = defaultdict(int) 
print(string_format_map('foo {bar}', d)) 
Смежные вопросы