Как добавить свойства в список dicts через понимание списка в python3? - PullRequest
1 голос
/ 15 мая 2019

У меня есть список диктов.Для каждого диктанта мне нужно передать одно из его свойств функции, а затем назначить новое свойство на основе результата этой функции.

Например: у меня есть список страниц сайта.Мне нужно перебрать их и, основываясь на URL, назначить имя автора свойству в dict.

for index, page in enumerate(pages):
    pages[index]['author'] = get_author(page['url'])

Это работает.Но загроможден и не чувствует себя питоном.pages[index] похоже на то, что мне не нужно делать в Python.

Есть ли способ сделать это через понимание списка?Или какой-нибудь другой более питонический способ?

pages = [??? for page in pages]

Ответы [ 4 ]

2 голосов
/ 15 мая 2019

Вы можете использовать такое list понимание:

result = [{**page, 'author': get_author(page['url'])} 
          for page in pages]

# This works too:

result = [dict(**page, author=get_author(page['url'])) 
          for page in pages]

# but is less preferred because it will fail for input containing non-string keys

Это создает новый dict для каждого оригинала dict с дополнительным ключом author, основанным на значении get_author применительно к значению, соответствующему клавише url.

Обратите внимание, что оно не изменяет оригинал list.

Пример:

def get_author(i):
    if i == 1:
        return 'hello'

    else:
        return 'bye'

pages = [{'url': 1},
         {'url': 2}]

result = [{**page, **{'author': get_author(page['url'])}} for page in pages]
print(result)

Выход:

[{'url': 1, 'author': 'hello'}, {'url': 2, 'author': 'bye'}]
1 голос
/ 15 мая 2019

Понимание списка создает список из существующего списка.В вашем случае вы хотите обновить существующие элементы списка.Понимание списка не подходит для этой работы.

Ваше решение может быть несколько улучшено, хотя:

for page in pages:
    page['author'] = get_author(page['url'])
0 голосов
/ 15 мая 2019

Я вижу два "питонических" решения:

  • Создание нового dict из распакованной страницы и нового значения 'author':
pages = [{**p, 'author': get_author(p['url'])} for p in pages]
  • Небольшой трюк с использованием оператора 'или':
pages = [p.update(author=get_author(p['url'])) or  p for p in pages]

Поскольку p.update () возвращает None, None or p всегда будет обновленной версией p.

Первый кажется более читабельным, но я считаю, что второй превосходит первый по производительности.

0 голосов
/ 15 мая 2019

Я не уверен, но может сработать следующее:

[pages[index]['author'] = get_author(page['url']) for index, page in enumerate(pages)]
...