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


кроме этого (или написания вспомогательной функции) я могу легко оценить и распечатать этот объект генератора в интерактивной оболочке?

1039   5  

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

    Ничего не найдено.