Python: печать выражения генератора?
в оболочке Python, если я ввожу список понимания, такие как:
>>> [x for x in string.letters if x in [y for y in "BigMan on campus"]]
я получаю красиво напечатанный результат:
['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']
то же самое для понимания словаря:
>>> {x:x*2 for x in range(1,10)}
{1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}
если я ввожу выражение генератора, я получаю не такой дружелюбный ответ:
>>> (x for x in string.letters if x in (y for y in "BigMan on campus"))
<generator object <genexpr> at 0x1004a0be0>
Я знаю, что могу это сделать:
>>> for i in _: print i,
a c g i m n o p s u B M
кроме этого (или написания вспомогательной функции) я могу легко оценить и распечатать этот объект генератора в интерактивной оболочке?
5 ответов:
короткий ответ:
делаешь
list()вокруг выражения генератора (почти) точно эквивалентно наличию[]квадратные скобки. Так что да, вы можете сделать>>> list((x for x in string.letters if x in (y for y in "BigMan on campus")))но вы можете просто сделать
>>> [x for x in string.letters if x in (y for y in "BigMan on campus")]Да, это превратит выражение генератора в понимание списка. Это то же самое, что и список вызовов() на нем. таким образом, способ сделать выражение генератора в список - это поставить скобки вокруг оно.
подробное описание:
выражение генератора является "голым"
forвыражение. Вот так:x*x for x in range(10)теперь вы не можете вставить это в строку самостоятельно, вы получите синтаксическую ошибку. Но вы можете поставить скобки вокруг него.
>>> (x*x for x in range(10)) <generator object <genexpr> at 0xb7485464>это иногда называют генераторным пониманием, хотя я думаю, что официальное название все еще является генераторным выражением, на самом деле нет никакой разницы, скобки существуют только для того, чтобы сделать синтаксис допустимым. Они не нужны, если вы передаете его в качестве единственного параметра функции, например:
>>> sorted(x*x for x in range(10)) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]в основном все другие понимания, доступные в Python 3 и Python 2.7, - это просто синтаксический сахар вокруг выражения генератора. Набор понятий:
>>> {x*x for x in range(10)} {0, 1, 4, 81, 64, 9, 16, 49, 25, 36} >>> set(x*x for x in range(10)) {0, 1, 4, 81, 64, 9, 16, 49, 25, 36}дикт постижений:
>>> dict((x, x*x) for x in range(10)) {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} >>> {x: x*x for x in range(10)} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}и список постижений под Python 3:
>>> list(x*x for x in range(10)) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> [x*x for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]под Python 2, Список понимание-это не просто синтаксический сахар. Но единственная разница заключается в том, что x будет под Python 2 просачиваться в пространство имен.
>>> x 9в то время как под Python 3 вы получите
>>> x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'x' is not definedэто означает, что лучший способ получить хорошую распечатку содержимого вашего выражения генератора в Python-сделать из него понимание списка! Однако это, очевидно, не будет работать, если у вас уже есть объект генератора. Делать это будет просто сделать список из одного генератор:
>>> foo = (x*x for x in range(10)) >>> [foo] [<generator object <genexpr> at 0xb7559504>]в таком случае вам нужно будет позвонить
list():>>> list(foo) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]хотя это и работает, но довольно глупо:
>>> [x for x in foo] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Вы можете просто обернуть выражение в вызове
list:>>> list(x for x in string.letters if x in (y for y in "BigMan on campus")) ['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']
в отличие от списка или словаря, генератор может быть бесконечным. Это не сработает:
def gen(): x = 0 while True: yield x x += 1 g1 = gen() list(g1) # never endsкроме того, чтение генератора изменяет его, поэтому нет идеального способа его просмотра. Чтобы увидеть образец выхода генератора, вы можете сделать
g1 = gen() [g1.next() for i in range(10)]
или вы всегда можете
mapнад итератором, без необходимости строить промежуточный список:>>> _ = map(sys.stdout.write, (x for x in string.letters if x in (y for y in "BigMan on campus"))) acgimnopsuBM
>>> list(x for x in string.letters if x in (y for y in "BigMan on campus")) ['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']
Comments