Улучшите код понимания списка, чтобы избежать вызова метода, используемого в понимании списка - PullRequest
0 голосов
/ 11 января 2019

Метод check_list_comprehension имеет понимание списка, которое возвращает правильный результат, но я вызвал другой метод внутри кода понимания списка, я хотел бы иметь только один метод, который будет возвращать тот же результат.

def check_list_comprehension():
    links = [{'link': 'test.com', 'params': {}}]
    previous_url_results = [{'for_next_params': {'seckey': 'gjgJG'}}, {'for_next_params': {'seckey': 'gjfggJG'}},
                            {'for_next_params': {'seckey': 'gjgJfgggG'}}]
    links = [_operations(link, previous_url['for_next_params'])
             for link, previous_url in itertools.product(links, previous_url_results)
             if 'for_next_params' in previous_url
             ]
    print(links)


def _operations(link, y):
    link['params'] = {**link['params'], **y}
    return link

check_list_comprehension()

Вывод этого кода:

[{'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}]

Пожалуйста, предложите лучший питонский способ сделать это.

1 Ответ

0 голосов
/ 11 января 2019

Во-первых, ваш результат неверен: обратите внимание, что вы получаете один и тот же секретный ключ для всех предметов. Это потому, что вы не копируете «достаточно» links ...

Что ж, вы можете исправить это, добавив copy() к вашему методу обновления, но если вы хотите, чтобы он был в одной строке, то почему бы не перестраивать каждое вхождение с нуля?

Другая проблема производительности заключается в том, что вы выполняете product , а затем , отфильтровывает нежелательные элементы вместо фильтрации входных элементов.

Вот мое решение для обеих проблем:

import itertools
def check_list_comprehension():
    links = [{'link': 'test.com', 'params': {}}]
    previous_url_results = [{'for_next_params': {'seckey': 'gjgJG'}}, {'for_next_params': {'seckey': 'gjfggJG'}},
                            {'for_next_params': {'seckey': 'gjgJfgggG'}}]
    links = [{'link':link['link'], 'params':previous_url['for_next_params']}
             for link, previous_url in itertools.product(links, (p for p in previous_url_results if 'for_next_params' in p))
             ]
    print(links)

результат:

[{'link': 'test.com', 'params': {'seckey': 'gjgJG'}}, {'link': 'test.com', 'params': {'seckey': 'gjfggJG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}]

Если params не пуст при запуске, этот код отбрасывает значение инициализации. Это можно исправить, изменив

{'link':link['link'], 'params':previous_url['for_next_params']}

до:

{'link':link['link'], 'params':{**link['params'], **previous_url['for_next_params']}

(этот вид словаря "сложение" недоступен до Python 3.5 Кстати, ссылка: Как объединить два словаря в одном выражении? )

...