2016-01-31 10 views
2

Я пытаюсь обвести голову вокруг общей идиомы генератора, с которой я сталкиваюсь в дикой природе. Я заметил это (и использовал его) в течение долгого времени, но никогда не беспокоился об этом. Пример идиомы с помощью функции игрушки:Почему работает следующее выражение генератора Python?

def contains_vowels(string): 
    vowels = set('aeiou') 

    if any((char in vowels) for char in string): 
     return True 

    return False 

Почему any((char in vowels) for char in string) работы, как ожидалось? Я получаю, что (char in vowels) является выражением генератора, но, например, (char in vowels) for char in string не является корректным генератором вне вызова функции.

Другими словами, если учесть, что приведенный выше код действителен, почему следующий код не работы:

for b in (char in vowels) for char in string: 
     print b 

(очевидно, делая все выражение генератор делает работы, как ожидалось:

for b in (char in vowels for char in string): 
     print b 

)

Я понимаю, что это немного глупый вопрос б Ответ не сразу интуитивен для меня. Это просто случай «потому что так работает синтаксис», или есть что-то, что мне не хватает?

+0

'(char in vowel)' не является выражением генератора. 'выражение для i в seq' является выражением генератора. 'x in foo' проверяет сдерживание. –

+0

Я получаю, что 'x in foo' проверяет наличие сдерживания. Я всегда считал, что '()' указывает генератор, потому что это единственный контекст, в котором я использовал этот шаблон, хотя то, что вы говорите, имеет смысл. Поэтому я предполагаю, что вы можете определить выражения генератора без круглых скобок внутри вызова функции ... но, например, я знаю, что это не работает при вызове функций с несколькими аргументами. Таким образом, более сложный ответ был бы полезен. – MCor

+0

Вы также будете «возвращать любые символы (char in vowels for char in string)», вам не нужен if/else –

ответ

3

Я получить, что (char in vowels) это выражение генератор,

На самом деле, это не так. Скобки в этом случае совершенно лишние, так как существует только один оператор in. Когда у вас больше операторов, скобки используются для установки порядка операций. (1+2)*3 == 9

(char in vowels) for char in string не является допустимым генератором вне вызова функции.

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

any(char in vowels for char in string) 
any((char in vowels for char in string)) 

Вне вызова функции генератор должен иметь круглые скобки.

(char in vowels for char in string) 
+0

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

+1

Да, это особый случай. –

+2

Это может быть немного сложно найти в документах, если вы не используете [python для функционального программирования] (https://docs.python.org/3/howto/functional.html) - поиск * круглых скобок, сигнализирующих о функции call также счет *. – JGreenwell