Насколько уместно вложение списков Python?

Я относительный новичок в питоне, теперь довольно комфортно с языком, но все еще занимаюсь вопросами того, что является "питоническим", а что нет. Мне было интересно, что думают люди по этому вопросу.

Например, возьмем эту строку кода для расчета средней стоимости за неделю аренды недвижимости, взятой из базы данных peewee:

    rental_avg_costperweek = сумма ([calcCostPerWeek(rental.price, rental.rental_freq)) для аренды в
                                 [LLSRental.select(LLSRental.id == this_id) для this_id в closest_rental_ids]]) \
                             / len(closest_rental_ids)

Он использует понимание вложенного списка, что может сбивать с толку.

В качестве альтернативы я мог бы вставить внутреннее понимание во временную переменную:

    closest_rental_records = [LLSRental.select(LLSRental.id == this_id) для this_id в closest_rental_ids]
    rental_avg_costperweek = sum([calcCostPerWeek(rental.price, rental.rental_freq) для аренды в closest_rental_records]) \
                             / len(closest_rental_ids)

Это может быть (немного) проще для чтения, но, будучи бывшим программистом на C++, у меня есть отвращение к созданию временных переменных исключительно для удобства чтения, поскольку это загромождает пространство имен и потенциально делает больше работы для сборщика мусора.

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

Таким образом, я склонен идти с первым вариантом, а не вторым, несмотря на указание "квартира лучше, чем вложенная"... но что думают ветераны питона?

Спасибо!
гс.

1 ответ

Решение

Я думаю, что оба не правы. Похоже, что вы делаете внутреннее понимание, потому что вы хотите избежать пересчета LLSRental.select(). Вам редко нужны внутренние понимания, если вы используете их надлежащим образом, потому что вы можете вкладывать их, как

all_the_inputs = [ process_value(x) for y in all_the_stuff for x in y ]

или что-то. Это хороший, но короткий пост, который объясняет это хорошо.

Тем не мение. Что-то вроде

rental_avg_costperweek = 0
for this_id in closest_rental_ids:
    rental = LLSRental.select(LLSRental.id == this_id)
    rental_avg_costperweek += calcCostPerWeek(rental.price, rental.rental_freq)
rental_avg_costperweek /= len(closest_rental_ids)

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

Другие вопросы по тегам