Подтвердить что ты не робот

Python: понимание (нет для g в g if (выход из g) и False)

Джеймс Пауэлл в своем кратком описании предстоящей презентации говорит, что он гордый изобретатель одного из самых гениальных однострочных Python:
(None for g in g if (yield from g) and False)

Я пытаюсь выяснить этот генератор, и, поскольку я живу с Python 2.7.x, я также отключился от выражения (yield from g).

Как мне это прочитать, и каков будет аналог python 2.7.x?


Какое замечательное обсуждение ниже! Я хочу проверить, правильно ли я это в основном.

>>> l = [10, 11, iter(xrange(5)), 12, 13]
>>> g = iter(l)
>>> flat_g = (None for g in g if (yield from g) and False)
>>> list(flat_g)
[10, 11, 0, 1, 2, 3, 4, 12, 13]

Это правда?

4b9b3361

Ответ 1

Это выражение похоже на способ написания кода-гольфа:

(a for b in g for a in b)

((Или, может быть, мотивация заключается в использовании делегаций генераторов, но IMHO-читаемость действительно страдает.))

Например:

#! /usr/bin/python3.3

g = ['abc', 'def', 'ghi']

a = (None for g in g if (yield from g) and False)
for x in a: print (x)

b = (a for b in g for a in b)
for x in b: print (x)

Печать дважды в сплющенном списке.

Я думаю, что он становится более разборчивым, если вы используете разные имена переменных:

(None for sublist in g if (yield from sublist) and False)

То же, что и

(42 for sublist in g if (yield from sublist) and False)

поскольку из-за something and False внешний генератор ничего не дает, в то время как внутренний генератор дает все элементы всех подписок (подгенераторы, субэлементы).

Возможно, это немного разъясняет, как это работает:

('Sublist {}'.format(idx) for idx, sublist in enumerate(g) if (yield from sublist) or True)

По-видимому, исходный генератор может быть упрощен до этого, опуская последний and False:

(None for sublist in g if (yield from sublist) )

Revision:

Благодаря Martijn Pieters, сражающемуся с моим упрямством, мне удалось увидеть, что (None for sublist in g if (yield from sublist) and False) и (None for sublist in g if (yield from sublist) ) не эквивалентны. Вот пример g, который делает разницу:

def f():
    yield 1
    return 2

def g():
    yield f()

a = (None for sublist in g() if (yield from sublist) )
for x in a: print(x)
a = (None for sublist in g() if (yield from sublist) and False)
for x in a: print(x)

Отпечатки:

1
None
1