2013-06-05 2 views
8

В нескольких случаях я хотел бы использовать синтаксис python для коротких замыканий в списках или генераторных выражений.Рекомендации по организации короткого замыкания

Вот простой список понимание, и эквивалентный цикл в Python:

my_list = [1, 2, 3, 'potato', 4, 5] 
[x for x in my_list if x != 'potato'] 

result = [] 
for element in my_list: 
    if element != 'potato': 
     result.append(element) 

Там не поддерживают на языке для понимания которые короткое замыкание. Предлагаемый синтаксис и эквивалент для цикла в Python:

[x for x in my_list while x != 'potato'] 
# --> [1, 2, 3] 

result = [] 
for element in my_list: 
    if element != 'potato': 
     result.append(element) 
    else: 
     break 

Он должен работать с произвольными итерируемыми, в том числе бесконечных последовательностей, и быть удлинению к генератору синтаксиса выражений. Я отдаю себе отчет в list(itertools.takewhile(lambda x: x != 'potato'), my_list) в качестве опции, но:

  • это не особенно вещий - не читаемыми, как некоторое время осмыслению
  • это, вероятно, не может быть столь же эффективным или быстро, как постижение CPython
  • его требует дополнительного шага для преобразования вывода, тогда как это может быть поставлено в понимание напрямую, например [x.lower() for x in mylist]
  • даже original author doesn't seem to like it much.

Мой вопрос в том, есть ли теоретическая морщина о том, почему не рекомендуется распространять грамматику на этот прецедент, или это просто невозможно, потому что python dev считает, что это было бы редко полезно? Это похоже на простое дополнение к языку и полезную функцию, но я, вероятно, не замечаю некоторых скрытых тонкостей или осложнений.

Связанный: this и this

+2

'result = []; any (x == 'potato' или result.append (x) для x в my_list) '. Хм ... нет, я думаю, что это хуже, чем takewhile :) –

+0

Я думаю, что вы с большей вероятностью получите хороший ответ в [python-dev] (http://mail.python.org/mailman/listinfo/python- dev) список рассылки. – Elazar

+0

@gnibbler: вы только что реализовали 'filterfalse', OP хочет остановить все добавления после того, как будет найден первый« картофель ». Попробуйте: 'found = []; result = []; any (x == 'potato' и not found.append (x) или result.append (x), если не найдено else None для x в my_list) ' – PaulMcG

ответ

6

Оказывается, как было отмечено @Paul McGuire, что было предложено в PEP 3142 и rejected Гвидо:

я не знаю, что было PEP для этого , Я отказываюсь от этого. Нет смысла тратить больше времени на это.

Он не дает объяснений. В списке рассылки, некоторые из пунктов против него являются:..

  • «[понимание есть] тщательно разработано 1 1 преобразование между несколькими вложенными заявлениями и одно выражением Но это предложение игнорирует и нарушает, что (here) «. То есть ключевое слово while не соответствует while в явном цикле - это только break.
  • «Это делает Python труднее учиться, потому что он добавляет еще одну вещь, чтобы учиться». (citated here)
  • Это добавляет еще одну разницу между выражениями генератора и пониманием списка. Кажется, что добавление этого синтаксиса, чтобы перечислить понимание, тоже не может быть и речи.

Я думаю, что одно основное отличие от обычного списка понимается в том, что while по своей сути является императивным, а не декларативным. Это зависит и диктует порядок исполнения, который не гарантируется языком (AFAIK).Думаю, именно по этой причине он не включен в понимание Хаскелла, из которого питон украл эту идею.

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

Конечно, Python обязательный язык в любом случае, но это вызовет проблемы.

А как насчет выбора из неупорядоченной коллекции?

[x for x in {1,2,3} while x!=2] 

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


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

[x for x in my_list from x != 'potato'] 

Что еще меньше связан с эквивалентной for конструкции, и на этот раз это не возможно короткое замыкание, если my_list просто итератор.

+0

Вы можете так же легко написать версию цикла for как «для x в my_set: ...». Это также не имеет смысла делать что-либо полезное. –

+1

Я думаю, что отсутствие опции «dropwhile» без введения нового ключевого слова (например, «после» в '[x for x в my_list after x == 'potato']') было одним из препятствий для принятия, но я действительно нравится идея - к сожалению, она уже была представлена ​​как PEP 3142 (http://www.python.org/dev/peps/pep-3142/) и отклонен. – PaulMcG

+0

@gnibbler Я ссылался на него явно, хотя и не в ясном виде: это произвольный ответ, который лучше избегать языком. В цикле 'for' просто нет реального способа его ограничить. – Elazar

Смежные вопросы