Форматирование ключей dict: AttributeError: объект' dict 'не имеет атрибута' keys()'


Как правильно форматировать ключи dict в строке?

Когда я делаю это:

>>> foo = {'one key': 'one value', 'second key': 'second value'}
>>> "In the middle of a string: {foo.keys()}".format(**locals())

Чего я ожидаю:

"In the middle of a string: ['one key', 'second key']"

Что я получаю:

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    "In the middle of a string: {foo.keys()}".format(**locals())
AttributeError: 'dict' object has no attribute 'keys()'
Но, как вы можете видеть, у моего диктатора есть ключи:
>>> foo.keys()
['second key', 'one key']
4 3

4 ответа:

Нельзя вызывать методы в заполнителях. Вы можете получить доступ к свойствам и атрибутам и даже индексировать значение - но вы не можете вызвать методы:

class Fun(object):
    def __init__(self, vals):
        self.vals = vals

    @property
    def keys_prop(self):
        return list(self.vals.keys())

    def keys_meth(self):
        return list(self.vals.keys())

Пример с методом (ошибка):

>>> foo = Fun({'one key': 'one value', 'second key': 'second value'})
>>> "In the middle of a string: {foo.keys_meth()}".format(foo=foo)
AttributeError: 'Fun' object has no attribute 'keys_meth()'

Пример со свойством (рабочим):

>>> foo = Fun({'one key': 'one value', 'second key': 'second value'})
>>> "In the middle of a string: {foo.keys_prop}".format(foo=foo)
"In the middle of a string: ['one key', 'second key']"

Синтаксис форматирования дает понять, что вы можете получить доступ только к атрибутам (a la getattr) или индексам (a la __getitem__) заполнителей (взятых из "синтаксис строки формата"):

За именем arg_name можно следовать любым числом индексных или атрибутивных выражений. Выражение вида '.name' выбирает именованный атрибут с помощью getattr(), в то время как выражение вида '[index]' выполняет поиск индекса с помощью __getitem__().


С Python 3.6 вы можете легко сделать это с f-строками, вам даже не нужно передавать locals:

>>> foo = {'one key': 'one value', 'second key': 'second value'}
>>> f"In the middle of a string: {foo.keys()}"
"In the middle of a string: dict_keys(['one key', 'second key'])"

>>> foo = {'one key': 'one value', 'second key': 'second value'}
>>> f"In the middle of a string: {list(foo.keys())}"
"In the middle of a string: ['one key', 'second key']"
"In the middle of a string: {}".format(list(foo.keys()))
"In the middle of a string: {}".format([k for k in foo])

Как было сказано другими выше, вы не можете сделать это так, как вы бы предпочли, вот дополнительная информация, чтобы следовать python string format вызова функции