469,286 Members | 2,476 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,286 developers. It's quick & easy.

PEP 289: Generator Expressions (please comment)

Peter Norvig's creative thinking triggered renewed interest in PEP 289.
That led to a number of contributors helping to re-work the pep details
into a form that has been well received on the python-dev list:

http://www.python.org/peps/pep-0289.html

In brief, the PEP proposes a list comprehension style syntax for
creating fast, memory efficient generator expressions on the fly:

sum(x*x for x in roots)
min(d.temperature()*9/5 + 32 for d in days)
Set(word.lower() for word in text.split() if len(word) < 5)
dict( (k, somefunc(k)) for k in keylist )
dotproduct = sum(x*y for x,y in itertools.izip(xvec, yvec))
bestplayer, bestscore = max( (p.score, p.name) for p in players )

Each of the above runs without creating a full list in memory,
which saves allocation time, conserves resources, and exploits
cache locality.

The new form is highly expressive and greatly enhances the utility
of the many python functions and methods that accept iterable arguments.
Raymond Hettinger
Jul 18 '05
72 3964
Rocco Moretti wrote:
...
I've never bought the argument that "comma's make the tuple." All the
So how do you explain:

x = 7,

print type(x)

pray?

To me, tuple packing/unpacking is a special case, not a general feature
That "7," up there is no packing nor unpacking. Just a tuple.

Of course, I'll change my opinion if Guido comes out and says that he
consciously intended all along for tuples to be defined by commas, and
Guido doesn't follow c.l.py, so if you're interested you'll have
to ask him directly. I think he's on record as saying so, more
than once, but can't be bothered to check -- this subthread's just
too silly and captious.

So let me see if I have this correct:

(Long Answer)

Genex's are required to have parenthesis around them except when they
would yield double parenthesis i.e. ((...)) - and the only place where
this is relevant is in function calls with one argument, or with
creating a tuple. (As genex's as base class lists and as a parameter
list would be illegal.) But with creating a tuple, you have to have a
comma to create a singleton, so that case doesn't matter either.
Right -- the "creating a tuple" wouldn't cause any double parentheses.

As a parenthetical (sic.) note, the only other cases of 'double
brackets' are {(...)} and [(...)], as python doesn't use <...> as
brackets. The first is illegal anyway - you can't create a dictionary
with just a genex. The second is covered in the PEP - that is:

"""
[x for x in S] # This is a list comprehension.
[(x for x in S)] # This is a list containing one generator
# expression.
"""
*and* the former is depreciated in favor of list(<genex>).
I think the spelling is "deprecated" -- and while I'd love it
to be, I don't think it is.

(Current Final short answer)

Parenthesis are required around genex's except when they are the *only*
parameter to a function. If either the first or last expression in a
genex is a tuple, they must have parenthesis around them.


Right, AFAIK.
Alex

Jul 18 '05 #51
Alex Martelli wrote:
"""
[x for x in S] # This is a list comprehension.
[(x for x in S)] # This is a list containing one generator
# expression.
"""
*and* the former is depreciated in favor of list(<genex>).

I think the spelling is "deprecated" -- and while I'd love it
to be, I don't think it is.


Aha, yes.

From dictionary.com (Quoting the American Heritage Dictionary):

"""
de·pre·ci·ate:
1. To lessen the price or value of.
2. To think or speak of as being of little worth; belittle. See
Usage Note at deprecate.

dep·re·cate:
1. To express disapproval of; deplore.
2. To belittle; depreciate.

Usage Note: The first and fully accepted meaning of deprecate is
“to express disapproval of.” But the word has steadily encroached on the
meaning of depreciate. It is now used, almost to the exclusion of
depreciate, in the sense “to belittle or mildly disparage,” as in He
deprecated his own contribution. In an earlier survey, this newer sense
was approved by a majority of the Usage Panel.
"""

Deprecate also has an additional technical usage entry from the Jargon File.

And you are right on the deprecated status. Quoth the PEP:

"""
List comprehensions will remain unchanged. For example:

[x for x in S] # This is a list comprehension.
[(x for x in S)] # This is a list containing one generator
# expression.

Unfortunately, there is currently a slight syntactic difference. The
expression:

[x for x in 1, 2, 3]

is legal, meaning:

[x for x in (1, 2, 3)]

But generator expressions will not allow the former version:

(x for x in 1, 2, 3)

is illegal.

The former list comprehension syntax will become illegal in Python 3.0,
and should be deprecated in Python 2.4 and beyond.
"""

I originally misread this. It should mean:
[x for x in 1, 2, 3] - is deprecated.
[x for x in (1, 2, 3)] - remains valid.

-Rocco

Jul 18 '05 #52
On Fri, Oct 24, 2003 at 05:42:44AM -0700, Chris Perkins wrote:
In fact, list comprehensions themselves become redundant syntactic
sugar under the new proposal:

[foo(x) for x in bar] ==> list(foo(x) for x in bar)


Is there any plan to deprecate list comprehension when we move to
Python3.0? I think the advantages are;

1. It's just a syntactic sugar, only saves 4 chars.

2. It solves loop variable leaking problem of list comprehension.
I think it causes less confusion to remove list comprehension than
to change the semantics of it not to leak loop variables when 3.0 comes.

3. We can

Jul 18 '05 #53
py****@rcn.com (Raymond Hettinger) wrote in message news:<5d**************************@posting.google. com>...
Peter Norvig's creative thinking triggered renewed interest in PEP 289.
That led to a number of contributors helping to re-work the pep details
into a form that has been well received on the python-dev list:

http://www.python.org/peps/pep-0289.html

In brief, the PEP proposes a list comprehension style syntax for....
Toward the end of the PEP, we have the following:
The utility of generator expressions is greatly enhanced when

combined with >reduction functions like sum(), min(), and max().
Separate proposals are >forthcoming that recommend several new
accumulation functions possibly >including: product(), average(),
alltrue(), anytrue(), nlargest(), nsmallest().
This is great. I'd like to request that alltrue() and anytrue() be
renamed forall() and exists(), repsectively. It would allow:

def prime(x):
return forall(x%y for y in xrange(2, math.sqrt(x)))

etc. This is a an opportunity to be mathematically precise, and I
think we should be. Python is going to have the universal and
existential operators in a very general syntax, so let's celebrate it
a little.

later,
Jess
Jul 18 '05 #54
au****@smartobject.biz (Jess Austin) wrote in message news:<b3**************************@posting.google. com>...
This is great. I'd like to request that alltrue() and anytrue() be
renamed forall() and exists(), repsectively.


While these are the mathematical names, I've almost always seen them
named "all" and "any" in the various (mostly functional) programming
languages I've seen them in.

Exists() also has the problem that to less mathematically-minded
people (or Perl programmers :)) it isn't exactly clear what it's
checking for. Certainly, one would expect a generator expressions
like "x%y for y in xrange(2, math.sqrt(x))" to "exist," since we can
see it in the code and look at it with our own eyes.

I think these names also read somewhat more clearly:

# Check if someone is yelling:
if all(str.isupper, line.split()):
print "Must be a flamewar."

and:

# Check if someone yelled at all:
if any(str.isupper, line.split()):
print "Someone yelled."

I believe both these examples are more easily readable with "all" and
"any" than they would be with "forall" and "exists."

Jeremy
Jul 18 '05 #55
Jeremy Fincher wrote:
...
I think these names also read somewhat more clearly:

# Check if someone is yelling:
if all(str.isupper, line.split()):
print "Must be a flamewar."

and:

# Check if someone yelled at all:
if any(str.isupper, line.split()):
print "Someone yelled."
I'm not sure what these calls are meant represent -- maybe an
interface similar to filter, i.e. a callable then a sequence?
The functions we're considering, whatever their names, would
in any case just take an iterator, so, e.g.:

if all(x.isupper() for x in line.split()):

and the like.

I believe both these examples are more easily readable with "all" and
"any" than they would be with "forall" and "exists."


I'll pass on that. Maybe. I think I still prefer alltrue and anytrue...
Alex

Jul 18 '05 #56
Alex Martelli <al***@aleax.it> wrote in message news:<g8***********************@news2.tin.it>...
I'm not sure what these calls are meant represent -- maybe an
interface similar to filter, i.e. a callable then a sequence?
The functions we're considering, whatever their names, would
in any case just take an iterator, so, e.g.:

if all(x.isupper() for x in line.split()):

and the like.
Yeah, I suppose that is the case :) I was stuck in FP mode (and
without-generator-expressions mode; I use those two functions in my
own code all the time)
I'll pass on that. Maybe. I think I still prefer alltrue and anytrue...


I'm afraid those names would inspire people to write code like this:

alltrue(bool(x) for x in someIterable)

I think the "true" in the function names might make people think it
constrains the type to be a bool, which, if it resulted in code as
above, would definitely be unfortunate.

Jeremy
Jul 18 '05 #57
rm
au****@smartobject.biz (Jess Austin) wrote in message news:<b3**************************@posting.google. com>...
py****@rcn.com (Raymond Hettinger) wrote in message news:<5d**************************@posting.google. com>...
Peter Norvig's creative thinking triggered renewed interest in PEP 289.
That led to a number of contributors helping to re-work the pep details
into a form that has been well received on the python-dev list:

http://www.python.org/peps/pep-0289.html

In brief, the PEP proposes a list comprehension style syntax for....


Toward the end of the PEP, we have the following:
The utility of generator expressions is greatly enhanced when

combined with >reduction functions like sum(), min(), and max().
Separate proposals are >forthcoming that recommend several new
accumulation functions possibly >including: product(), average(),
alltrue(), anytrue(), nlargest(), nsmallest().
This is great. I'd like to request that alltrue() and anytrue() be
renamed forall() and exists(), repsectively. It would allow:

def prime(x):
return forall(x%y for y in xrange(2, math.sqrt(x)))

etc. This is a an opportunity to be mathematically precise, and I
think we should be. Python is going to have the universal and
existential operators in a very general syntax, so let's celebrate it
a little.

later,
Jess

maybe allfalse() should be included aswell?

rm
Jul 18 '05 #58
Python doesn't use iftrue and whentrue, so why should it use alltrue and
anytrue? I vote for all and any.

"Jeremy Fincher" <tw*********@hotmail.com> wrote in message
news:69**************************@posting.google.c om...
Alex Martelli <al***@aleax.it> wrote in message news:<g8***********************@news2.tin.it>...
I'm not sure what these calls are meant represent -- maybe an
interface similar to filter, i.e. a callable then a sequence?
The functions we're considering, whatever their names, would
in any case just take an iterator, so, e.g.:

if all(x.isupper() for x in line.split()):

and the like.


Yeah, I suppose that is the case :) I was stuck in FP mode (and
without-generator-expressions mode; I use those two functions in my
own code all the time)
I'll pass on that. Maybe. I think I still prefer alltrue and

anytrue...
I'm afraid those names would inspire people to write code like this:

alltrue(bool(x) for x in someIterable)

I think the "true" in the function names might make people think it
constrains the type to be a bool, which, if it resulted in code as
above, would definitely be unfortunate.

Jeremy

Jul 18 '05 #59
Mark Hahn wrote:
Python doesn't use iftrue and whentrue, so why should it use alltrue
and
anytrue? I vote for all and any.


Well said.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \ Sanity is a cozy lie.
\__/ Susan Sontag
Jul 18 '05 #60
ro*********@yucom.be (rm) wrote in message news:<9f**************************@posting.google. com>...
maybe allfalse() should be included aswell?

rm


allfalse() isn't necessary; it's equivalent to "not any()", "not
exists()", "not anytrue()", or whatever depending on what is decided
for the existential form. Similarly, anyfalse() is equivalent to "not
all()", "not forall()", etc. Actually, that last example sounds
terrible, so I'm withdrawing my "forall" suggestion for the universal
form.

In the interests of orthogonality, I'd advise against the {any,
all}false() forms. It seems like the consensus is "all" and "any".
This makes sense to me, and I think this will be a great addition to
the language.

later,
Jess
Jul 18 '05 #61
au****@smartobject.biz (Jess Austin) wrote in message news:<b3**************************@posting.google. com>...
It seems like the consensus is "all" and "any".


Not necessarely. I prefer "alltrue" and "anytrue", for instance.

Michele
Jul 18 '05 #62
rm
au****@smartobject.biz (Jess Austin) wrote >
It seems like the consensus is "all" and "any".


which exists as well in SQL

e.g.

select ...
from ...
where x > any ( sub-select )

or

select ...
from ...
where x > all ( sub-select )

but SQL supports the following as well

select ...
from ...
where exists ( sub-select )

bye,
rm
Jul 18 '05 #63
rm wrote:
au****@smartobject.biz (Jess Austin) wrote >
It seems like the consensus is "all" and "any".

which exists as well in SQL


....with a subtly different meaning...
where x > any ( sub-select )
I can just imagine the fun somebody's going to have after
coding, e.g.:

while x > any( ... ) :
...
where exists ( sub-select )


That's another function, in Python terms. We could
code the SQL any, all and exists (taking any iterator or
iterable argument) roughly as follows:
class any(object):

def __init__(self, it):
" invoked by any(it) "
self.it = iter(it)

def __lt__(self, x):
" invoked by x > any(it) &c "
for item in self.it:
if x > item: return True
else: return False
# assuming x > any([]) is to be false

# and similarly for other comparisons
class all(object):

def __init__(self, it):
" invoked by all(it) "
self.it = iter(it)

def __lt__(self, x):
" invoked by x > all(it) &c "
for item in self.it:
if not (x > item): return False
else: return True
# assuming x > all([]) is to be true

# and similarly for other comparisons
def exists(it):
" invoked by exists(it) "
for item in it: return True
else: return False
# assuming exists([]) is to be false
I don't think the SQL semantics for any and all merge _well_ with
those that people want around here, though it would technically be
possible to also define a __nonnull__ in each class to do the
obvious checks -- I think it would be rather confusing to allow
both "if x > all(...):" and "if all(...):" with 'all' meaning such
different things in the two cases. Similarly for 'any'. And
'exists' to mean 'has some true items' is of course very different
from the SQL meaning of 'exists' to mean "it's not empty"...!

I'd just love to have such meanings for any, all, and exists, but
I believe it's not going happen -- because people around here don't
like the spelling 'alltrue' to mean "all items are true" and so on.
Ah well, there will be other ways to spell similar semantics,
though goofy rather than elegant ones -- e.g., instead of:

if x > all(theitems):

we'll just have to code:

if all(x>item for item in theitems):
In any case, the SQL meaning isn't extensible to Python's chaining
of comparisons when we only have an iterator (not an iterable) --
in that case,

if x > all(itemsiterator) > y :

can't be made to mean what we'd obviously _like_ it to mean
without spending the memory to save all the items as they go,
since it's evaluated equivalently to:

_aux = all(itemsiterator)

if (x > _aux) and (_aux > y) :
...

and if it comes to the comparison after the implied and, the
itemsiterator is exhausted by that time. So, maybe, it _is_
for the better that the apparently popular preference for 'all'
to mean 'alltrue' stops us from having 'all' work like in SQL
instead - it does save us from potentially non-obvious behavior
when both comparison chaining and iterators-as-opposed-to-
iterables are simultaneously involved.
Alex

Jul 18 '05 #64
Michele Simionato wrote:
au****@smartobject.biz (Jess Austin) wrote in message
news:<b3**************************@posting.google. com>...
It seems like the consensus is "all" and "any".


Not necessarely. I prefer "alltrue" and "anytrue", for instance.


Me too, FWIW. But more important is, where are these operators
going to _live_ -- the builtins are definitely _out_ , judging by
Guido's recent reactions.

I think we need a companion module to itertools. The functions
in itertools *produce* useful iterators; we need a module for
functions that usefully *consume* iterators. Yes, a few, in each
case, judged more useful than others, are built-ins (iter,
enumerate, reversed as producers; sum, min, and max as consumers).

But, most others won't be -- so we have itertools and need [good
name for "iterator consumers" sought -- accumulators?). This, btw,
will usefully afford e.g.
from accumulators import any as anytrue
or viceversa, mitigating the effect of a dlsliked name being chosen.
Other candidates (names can surely be enhanced...) in random order:

average(numbers)
average_and_variance(numbers) # returns tuple -- average, variance
median(numbers)

highest(N, numbers) # return list of N highest numbers
lowest(N, numbers) # ditto for lowest
# note: highest and lowest might get optional key= -- like lists' sort
# method has added in 2.4

take(N, numbers) # ditto for the first N
exists(xs) # true if xs is non-empty

repeatcall(f, xs, result=None)
# like: for x in xs: f(x)
return result
# typical uses:
# # just concatenate a lots of sequences into list allitems
# allitems = []
# repeatcall(allitems.extend, lotsofsequences)
# # merge a lot of dictionaries and loop on merged result dict d
# d = {}
# for k in repeatcall(d.update, ds, d): ...
Alex

Jul 18 '05 #65
> [Jess Austin]
...It seems like the consensus is "all" and "any".


Oh no! Their mathematical names are "forall" and "exists" and that is
what they should be IMO. Any programmer I can think of is familiar
with "forall" and "exists" in mathematics.

--
I have learned silence from the talkative, toleration from the
intolerant, and kindness from the unkind.
-- Kahlil Gibran
Jul 18 '05 #66
If it's a vote, I'm voting for 'all' and 'any'. They are short, natural and symmetric.
G-:
[Jess Austin]
...It seems like the consensus is "all" and "any".

Jul 18 '05 #67
Raymond Hettinger wrote:

http://www.python.org/peps/pep-0289.html

In brief, the PEP proposes a list comprehension style syntax for
creating fast, memory efficient generator expressions on the fly:

sum(x*x for x in roots)
min(d.temperature()*9/5 + 32 for d in days)
Set(word.lower() for word in text.split() if len(word) < 5)
dict( (k, somefunc(k)) for k in keylist )
dotproduct = sum(x*y for x,y in itertools.izip(xvec, yvec))
bestplayer, bestscore = max( (p.score, p.name) for p in players )

Each of the above runs without creating a full list in memory,
which saves allocation time, conserves resources, and exploits
cache locality.


+3.1415926535897931 for me.

Bruno

Jul 18 '05 #68
hw***@hotmail.com (Will Stuyvesant) writes:
[Jess Austin]
...It seems like the consensus is "all" and "any".


Oh no! Their mathematical names are "forall" and "exists" and that is
what they should be IMO. Any programmer I can think of is familiar
with "forall" and "exists" in mathematics.


Far from all Python programmers have been exposed to quantificational
logic.
John
Jul 18 '05 #69
mi**@pitt.edu (Michele Simionato) writes:
au****@smartobject.biz (Jess Austin) wrote in message

news:<b3**************************@posting.google. com>...
It seems like the consensus is "all" and "any".


Not necessarely. I prefer "alltrue" and "anytrue", for instance.


+1
John
Jul 18 '05 #70
Will Stuyvesant wrote:
Oh no! Their mathematical names are "forall" and "exists" and that is
what they should be IMO.


Actually, their mathematical names are an upside-down "A"
and an upside-down "E", which are often pronounced "for
all" and "there exists", but other pronunciations are
possible.

In Python, "all" and "any" would be closest to the
conciseness of the mathematical symbols, IMO. Until
we get to use Unicode in identifiers, anyway...

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #71

"Greg Ewing (using news.cis.dfn.de)" <g2********@sneakemail.com> wrote in
message news:bo*************@ID-169208.news.uni-berlin.de...
Will Stuyvesant wrote:
Oh no! Their mathematical names are "forall" and "exists" and that is
what they should be IMO.
Actually, their mathematical names are an upside-down "A"
and an upside-down "E", which are often pronounced "for
all" and "there exists", but other pronunciations are
possible.

In Python, "all" and "any" would be closest to the
conciseness of the mathematical symbols, IMO. Until
we get to use Unicode in identifiers, anyway...


Hasten the day!

As far as I'm concerned, 3.0 seems to be about as
likely as my seeing a real unicorn.

John Roth
--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #72
In article <bo*************@ID-169208.news.uni-berlin.de>, Greg Ewing
(using news.cis.dfn.de) wrote:
Will Stuyvesant wrote:
Oh no! Their mathematical names are "forall" and "exists" and that is
what they should be IMO.


Actually, their mathematical names are an upside-down "A"
and an upside-down "E", which are often pronounced "for
all" and "there exists", but other pronunciations are
possible.


While we're nit-picking, I'd like to point out that the "E" isn't
upside-down -- it's mirrored (or rotated 180 degrees or whatever), so
it's horizontal edges point left. :)

As for the "forall" and "exists" -- these are the LaTeX names for
these symbols. Given that Guido has already used LaTeX as a motivation
for enumerate(), that might speak in favor of these names (even though
"all" and "any" seem better to me too...)

--
Magnus Lie Hetland "In this house we obey the laws of
http://hetland.org thermodynamics!" Homer Simpson
Jul 18 '05 #73

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.