py3k printing generators -- not!

S

samwyse

The one thing that's killing me in Python 3000 is that every time I
try to print something, it seems like I get <generator object
<genexpr> at 0x01BAF508>. Googling only found one reference, a
posting elsewhere by one Carl Johnson (aka carlj7,
http://www.artima.com/forums/flat.jsp?forum=106&thread=211200#275387),
which apparently was never answered. Is anyone else finding this
bothersome, or is it entirely due to my FP background?

Always saying "print(','.join(x))" gets tiresome in a hurry. I've
thought about defining my own function "prnt" that wraps print and
fixes generators, but that requires me to get their type, which
despite the claims of "help(type(x for x in range(0)))" cannot be
found in builtins. How are other solving this?
 
C

Carl Banks

The one thing that's killing me in Python 3000 is that every time I
try to print something, it seems like I get <generator object
<genexpr> at 0x01BAF508>.  Googling only found one reference, a
posting elsewhere by one Carl Johnson (aka carlj7,http://www.artima.com/forums/flat.jsp?forum=106&thread=211200#275387),
which apparently was never answered.  Is anyone else finding this
bothersome, or is it entirely due to my FP background?

Always saying "print(','.join(x))" gets tiresome in a hurry.  

What about print(list(x))
I've
thought about defining my own function "prnt" that wraps print and
fixes generators, but that requires me to get their type, which
despite the claims of "help(type(x for x in range(0)))" cannot be
found in builtins.

Interestingly, the fact that it wasn't in builtins didn't stop you
from being able to pass the type to the help() function. I wonder if
you can use the same trick to obtain the type for use in your prnt()
function.

(Failing that, you could use "from types import GeneratorType".)
 How are other solving this?

In my experience, if you want a custom print function that prints
things the way you want, you have to write it yourself. People's
expectations are too different.


Carl Banks
 
B

bearophileHUGS

samwyse:
Always saying "print(','.join(x))" gets tiresome in a hurry.  I've
thought about defining my own function "prnt" that wraps print and
fixes generators, but that requires me to get their type,

Why do you need to know their type?
Isn't something like this enough?

def pr(it):
txt = "".join(map(str, it))
print(txt)

That little function can be improved in many ways.

despite the claims of "help(type(x for x in range(0)))"
cannot be found in builtins.

Python can yield mixed types (nearly never recommended):

def foo():
yield 1
yield "hello"
yield 1.5

Bye,
bearophile
 
S

samwyse

What about print(list(x))

Yeah, I like that. Or, to save some typing:
prnt = lambda x: print(list(x))
Interestingly, the fact that it wasn't in builtins didn't stop you
from being able to pass the type to the help() function.  I wonder if
you can use the same trick to obtain the type for use in your prnt()
function.

Of course, but it would mean evaluating an expression every time I
defined my function. That just seems unhygenic
(Failing that, you could use "from types import GeneratorType".)

Ah! I should've thought of that.
In my experience, if you want a custom print function that prints
things the way you want, you have to write it yourself.  People's
expectations are too different.

Well, that's why I rferenced the other article,
http://www.artima.com/forums/flat.jsp?forum=106&thread=211200#275387),
to show that other people have the same expectations. (In the
article, Carl Johnson correctly points out that the real problem is
that str() responds to generators differently than do the other
collection types.)
 
S

Steven D'Aprano

The one thing that's killing me in Python 3000

Python 3000 was vapourware. When the vapour condensed into liquid, it was
renamed Python 3. Right now, the only vapourware is Python4000, which may
or may not be created by Guido's heir some time in the 2020s.

is that every time I try
to print something, it seems like I get <generator object <genexpr> at
0x01BAF508>.

"Every time"? Really? Even when you print an object which isn't a
generator?

Googling only found one reference, a posting elsewhere by
one Carl Johnson (aka carlj7,
http://www.artima.com/forums/flat.jsp?forum=106&thread=211200#275387),
which apparently was never answered.

Ignoring Carl's totally pointless "mycond()" function, he apparently
wants type(iterable)(i for i in iterable) to give iterable:
it = [1, 2]
type(it)(i for i in it)
[1, 2]


But that can't work for arbitrary iterables:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot convert dictionary update sequence element #0 to a
sequence


Nor will it work for generator objects themselves:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'generator' instances


So Carl's suggestion can't be applied universally, it can only hold for
some iterables. It doesn't even hold for all sequences, with strings a
conspicuous example. In fact, that's what Carl is complaining about:
'<generator object <genexpr> at 0xb7ce3d24>'


He apparently would prefer str(i for i in "abc") to return "abc".
However, you seem to prefer "a,b,c" instead. So what you would prefer,
and what Carl would prefer, are different.

Either way though, there's a fatal flaw in the idea: printing an object
shouldn't consume the object, but that's what you want. Unlike a list or
a tuple, a generator is *code*, not a data type. It produces values when
and as asked. So there's no way to peek inside a generator and see the
values that it will produce, consequently, for str() to behave as you and
Carl want, it has to run the generator to completion, performing an
arbitrarily large amount of work (and perhaps, for non-terminating
generators, never finishing!) before you can print it. And then, having
printed it, the generator is now exhausted. Try to print it again, and
you'll get the empty string.

Calling list() on a generator is different: it is *designed* to exhaust
the generator. I'd be upset if print() and/or str() did the same thing.

I'd also be upset if generators looked like a string when they're not:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'generator' object has no attribute 'upper'



[...]
I've
thought about defining my own function "prnt" that wraps print and fixes
generators, but that requires me to get their type, which despite the
claims of "help(type(x for x in range(0)))" cannot be found in builtins.
How are other solving this?

I'm not "solving" this, because I don't think this is a problem that
needs solving. But if you want a custom print function, this should work:

def print(*values, **kwargs):
from builtins import print as pr
gen = type(x for x in [1,2])
values = [','.join(str(s) for s in obj) if type(obj) is gen
else obj for obj in values]
pr(*values, **kwargs)
 
T

Terry Reedy

samwyse said:
The one thing that's killing me in Python 3000

py3.0 or py3.1, but the 'problem' you complain about has nothing to do
with those versions in particular.
is that every time I try to print something, it seems like I get <generator object
<genexpr> at 0x01BAF508>.

Nor does it have anything is particular to do with generator objects.
Str(function/class/module/and-many-others) prints similarly. Since
forever, str(ob) == ob.__str__() == type(ob).__str__(ob). And what you
see above is the default template filled in for a particular object.

Built-in concrete collections over-ride the default and return a string
with their contents because they can do that without harm other than
possibly producing a very long string. When the collections are large,
one might want a custom function that instead formats a string with a
limited number of examples and the total count.

A 3.0 range object, a virtual collection, could do that too, but since
there is a regular pattern, it prints a condensed representation.
Aren't you glad, actually, that range(1000000000) prints as "range(0,
1000000000)" instead of listing the billion numbers it produces when
iterated, as you seem to be asking for?
Googling only found one reference, a
posting elsewhere by one Carl Johnson (aka carlj7,
http://www.artima.com/forums/flat.jsp?forum=106&thread=211200#275387),

A bogus complaint that the constructor for highly specialized class str
acts differently from those of the general collection classes set,
tuple, and list. Str is actually not a collection class in the way that
set, tuple, list, dict, and many others are.

Terry Jan Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top