Ответ 1
Так как Python 2.5, yield <value>
является выражением, а не выражением. См. PEP 342.
Код ужасно и излишне уродливый, но он законный. Его центральный трюк использует f((yield x))
внутри выражения генератора. Вот более простой пример того, как это работает:
>>> def f(val):
... return "Hi"
>>> x = [1, 2, 3]
>>> list(f((yield a)) for a in x)
[1, 'Hi', 2, 'Hi', 3, 'Hi']
В принципе, использование выражения yield
в выражении генератора заставляет его создавать два значения для каждого значения в исходном итерабельном. Поскольку выражение генератора повторяется по списку строк, на каждой итерации yield x
сначала выводит строку из списка. Целевое выражение гена xp f((yield x))
, поэтому для каждого значения в списке "результат" выражения генератора представляет собой значение f((yield x))
. Но f
просто игнорирует свой аргумент и всегда возвращает строку опций "-o"
. Таким образом, каждый шаг через генератор дает сначала строку значений ключа (например, "x=1"
), затем "-o"
. Внешний list(reversed(list(...)))
просто делает список из этого генератора, а затем меняет его так, что "-o"
будет использоваться перед каждым вариантом, а не после.
Однако для этого нет оснований делать это. Существует ряд гораздо более читаемых альтернатив. Возможно, наиболее явным является просто:
kvs = [...] # same list comprehension can be used for this part
result = []
for keyval in kvs:
result.append("-o")
result.append(keyval)
return result
Даже если вам нужен краткий "умный" код, вы все равно можете просто сделать
return sum([["-o", keyval] for keyval in kvs], [])
Само понимание списка kvs
- это странное сочетание попыток чтения и нечитаемости. Это проще написано:
kvs = [str(optName) + separator + str(optValue) for optName, optValue in options.items()]
Вам следует подумать о том, чтобы организовать "вмешательство" для тех, кто положил это в свою кодовую базу.