В Python лучше использовать понимания списка или циклы foreach?

Какое из следующего лучше для использования и почему?

Метод 1:

for k, v in os.environ.items():
       print "%s=%s" % (k, v)

Метод 2:

print "\n".join(["%s=%s" % (k, v) 
   for k,v in os.environ.items()])

Я склонен приводить к первому как более понятное, но это могло бы просто быть то, потому что я плохо знаком с пониманиями Python и списка, являются все еще несколько внешними мне. Второй путь считают большим количеством Pythonic? Я предполагаю, что нет никакого различия в производительности, но я могу быть неправым. Каковы были бы преимущества и недостатки этих 2 методов?

(Код, взятый от Погружения в Python)

36
задан Bill the Lizard 3 August 2012 в 17:46
поделиться

7 ответов

Если итерация выполняется из-за ее побочного эффекта (как в вашем примере «печати»), то цикл будет более понятным.

Если итерация выполняется для построения составного значения, то понимание списков обычно более читабельно.

38
ответ дан 27 November 2019 в 05:22
поделиться

Обработка списков должна выполняться на уровне C, поэтому при большом цикле понимание списков - хороший выбор.

3
ответ дан 27 November 2019 в 05:22
поделиться

Конкретные примеры кода, которые вы выбрали, не демонстрируют никаких преимуществ понимания списка, потому что он (неправильно) используется для тривиальной задачи печати. В этом простом случае я бы выбрал простой цикл for.

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

Пример, который наглядно продемонстрирует превосходство list comp, можно сделать, заменив пример print на пример с созданием еще одного фактического списка путем добавления к одному на каждой итерации цикла for:

L = []
for x in range(10):
    L.append(x**2)

Дает тот же L, что и:

L = [x**2 for x in range(10)]
25
ответ дан 27 November 2019 в 05:22
поделиться

Я считаю, что первый пример лучше - менее подробный, более ясный и более читаемый.

На мой взгляд, в конце концов, следуйте тому, что лучше всего передает ваше намерение:

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

- из «Структура и интерпретация компьютерных программ» Абельсона и Сассмана

Между прочим, поскольку вы только начинаете изучать Python, сразу же начните изучать новый синтаксис форматирования строк :

for k, v in os.environ.items():
    print "{0}={1}".format(k, v)
15
ответ дан 27 November 2019 в 05:22
поделиться

Понимание списка более чем в два раза быстрее, чем явный цикл. Если взять за основу вариацию Бена Джеймса, но заменить x**2 на более тривиальную функцию x+2, то получатся две альтернативы:

def foo(n):
  L = []
  for x in xrange(n):
    L.append(x+2)
  return L


def bar(n):
  return [x+2 for x in xrange(n)]

Результат подсчета времени:

In [674]: timeit foo(1000)
10000 loops, best of 3: 195 us per loop

In [675]: timeit bar(1000)
10000 loops, best of 3: 81.7 us per loop

С большим отрывом выигрывает понимание списка.

Я согласен с тем, что читабельность должна быть приоритетнее оптимизации производительности. Однако читабельность находится в поле зрения зрителя. Когда я только начинал изучать Python, понимание списков было странной вещью, которую мне было трудно понять! Но как только я привык к нему, он стал действительно удобной короткой ручной нотацией. Если вы хотите стать знатоком Python, вы должны овладеть пониманием списков.

13
ответ дан 27 November 2019 в 05:22
поделиться

Я согласен с @Ben, @Tim, @Steven:

  • удобочитаемость - это самая важная вещь ("импортируйте это", чтобы напомнить себе о том, что есть)
  • listcomp может или может быть не намного быстрее, чем версия с итеративным циклом ... это зависит от общего количества вызовов функций, которые выполняются
  • , если вы действительно решите использовать listcomps с большими наборами данных, это лучше использовать выражения генератора вместо

Пример:

print "\n".join("%s=%s" % (k, v) for k,v in os.environ.iteritems())

в приведенном выше фрагменте кода я внес два изменения ... Я заменил listcomp на genexp и изменил вызов метода iteritems () . [эта тенденция развивается, как и в Python 3, iteritems () заменяет и переименовывается в items () .]

2
ответ дан 27 November 2019 в 05:22
поделиться

На мой взгляд, первый, потому что:

  • Он не создает огромную строку.
  • Он не создает огромный список (может быть легко исправлен с помощью генератора, удалив []).

В обоих случаях вы получаете доступ к элементам одинаково (используя итератор словаря).

4
ответ дан 27 November 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: