2016-11-14 4 views
5

Python позволяет «if» состояние в списковых, например:условия Подворье в цикле

[l for l in lines if l.startswith('example')] 

Эта функция отсутствует в обычной «for» цикла, так и в отсутствии:

for line in lines if line.startswith('example'): 
    statements 

нужно оценить состояние в цикле:

for line in lines: 
    if line.startswith('example'): 
     statements 

или встраивать генератор, например:

for line in [l for l in lines if l.startswith('example')]: 
    statements 

Правильно ли я это понимаю? Есть ли лучший или более пифонический способ, чем перечисленные выше, для достижения того же результата добавления условия в цикл for?

Обратите внимание, что в качестве примера выбрано «линии», любая коллекция или генератор могут быть там.

+0

Вы спрашиваете, как получить сложные условия в цикле ? –

+3

Но это точно такие же. Вы читаете понимание списка слева направо, и оно содержит ту же функциональность, что и полный цикл. –

+0

Не могли бы вы сказать, в чем именно заключается ваш вопрос? –

ответ

2

Несколько приятных идей пришли из других ответов и комментариев, но я думаю, что this recent discussion on Python-ideas и its continuation - лучший ответ на этот вопрос.

Подводя итог: идея уже обсуждалась в прошлом, и выгоды не кажется достаточно, чтобы мотивировать изменения синтаксиса, принимая во внимание:

  • повышенной сложности языка и влияние на кривой обучения

  • технических изменений во всех реализациях: CPython, Jython, PyPy ..

  • возможных странных ситуации, что крайнее использование synthax может привести

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

This message и this one красиво суммировать возможные альтернативы (почти уже появились на этой странице, а) к соединению Условный оператор в для цикла:

# nested if 
for l in lines: 
    if l.startswith('example'): 
     body 

# continue, to put an accent on exceptional case 
for l in lines: 
    if not l.startswith('example'): 
     continue 
    body 

# hacky way of generator expression 
# (better than comprehension as does not store a list) 
for l in (l for l in lines if l.startswith('example')): 
    body() 

# and its named version 
def gen(lines): 
    return (l for l in lines if l.startswith('example')) 
for line in gen(lines): 
    body 

# functional style 
for line in filter(lambda l: l.startswith('example'), lines): 
    body() 
+1

'filter' должен быть наоборот:' filter (lambda l: l.startswith ('example'), lines) ' –

+0

@tobias_k сделано, спасибо! – Pintun

1

Возможно, не Pythonic, но вы могли бы filter линии.

for line in filter(lambda l: l.startswith('example'), lines): 
    print(line) 

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

def my_filter(line): 
    return line.startswith('example') or line.startswith('sample') 

for line in filter(my_filter, lines): 
    print(line) 

Я хотел бы сказать, что наличие условия внутри цикла лучше, потому что вы не поддерживаете «отфильтрованной» список в памяти, как вы итерацию по линиям.

Итак, что бы просто

for line in file: 
    if not my_filter(line): 
     continue 
    # statements 
+0

Хороший, спасибо. Я так и думал об этом, но забыл добавить его. Хотя, я все еще думаю, что у него нет читаемости только наличия условия в самом цикле. Интересно, я первый почувствовал необходимость такого синтаксиса. – Pintun

+1

@Pintun FWIW, это было обсуждено не так давно на Python-идеях, где вы можете прочитать ответы некоторых из основных разработчиков CPython: [сентябрь 2016] (https://mail.python.org/pipermail/python -ideas/2016-September/042270.html) и продолжения работы [октябрь 2016 года] (https://mail.python.org/pipermail/python-ideas/2016-October/042640.html). Из того, что я собираю, эта идея возникла несколько раз и раньше. Я настоятельно рекомендую вам прочитать всю тему. –

+0

@suspicousdog спасибо, там я нашел все, что искал: ссылка на предыдущее обсуждение, технические и эстетические причины в пользу и против изменений, отличные примеры альтернатив. Я нашел особенно интересным [это] (https://mail.python.org/pipermail/python-ideas/2016-September/042273.html) сообщение, которое я буду использовать в качестве ориентира для самостоятельного ответа. Я не знал [Python-идей] (https://mail.python.org/mailman/listinfo/python-ideas), отличная ссылка! – Pintun

0

его не о том, что функция отсутствует, я не могу думать ни о каком способе это может быть сделано, за исключением некоторых особых случаев. (l for l in lines if l.startswith('example')) - это объект-генератор, а переменная l является локальной для этого объекта. for видит только то, что было возвращено генератором __next__.

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

for line in (line for line in lines if l.startswith('example')): 
    foo(line) 

безопасно, потому что эти два line «s в различных областях.

Кроме того, генератору не нужно возвращать только его локальную переменную. Он может оценивать любое выражение. Как бы вы это сократили?

for line in (foo(line)+'bar' for line in lines if line.startswith('example')): 
    statements 

Предположим, у вас есть список списков

for l in (l[:] for l in list_of_lists if l): 
    l.append('modified') 

Это не должно добавляться к первоначальным спискам.

0

Есть ли лучший или более пифонический способ, чем перечисленные выше для достижения того же результата добавления условия в цикл for?

Нет, нет, и не должно быть; , что послужило основанием для того, почему в этом списке попали перечни понятий. Из corresponding PEP:

списковых обеспечивают более краткий способ для создания списков в ситуациях, когда бы в настоящее время используется map() и filter() и/или вложенных циклов.

Составы списка представляют собой альтернативу для вложенных for, if s; зачем вам альтернативой альтернативе?

Если вам нужно использовать if с for, вы вставляете его внутри него, если вы не хотите этого делать, вы используете понимание списка. Плоский лучше, чем вложенныйнопоказатель удобочитаемости; позволяя if, это приведет к длинным уродливым линиям, которые сложнее визуально разобрать.

+0

«Перечисления списков представляют собой альтернативу для вложенных, ifs, почему вы хотите альтернативу альтернативе?» Они не являются альтернативой в этом случае: для списка понятий по-прежнему нужен цикл for-loop для повторения. – Pintun

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