To confuse a newbies and old hands alike, Bengt Richter wrote: Need something more straightforward , e.g., a wrapped one-liner:
>>> def guess(n=3): print ("You're right!", 'No more tries for >>> you!!!')[n-1 in ... (x for x in xrange(n) for t in [raw_input('Gues s my name: ')=='Ben'] ... if not t or iter([]).next())] ... >>> guess()
To make it a bit clearer, a StopIteration raised in a generator expression
silently terminates that generator:
def stop(): raise StopIteration
.... list(i for i in range(10) if i < 5 or stop())
[0, 1, 2, 3, 4]
In a list comprehension, on the other hand, it is propagated:
[i for i in range(10) if i < 5 or stop()]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in stop
StopIteration
Is that an intentional difference?
Peter 16 2301
Peter Otten wrote: To confuse a newbies and old hands alike, Bengt Richter wrote:
got me for one:) To make it a bit clearer, a StopIteration raised in a generator expression silently terminates that generator:
*any* exception raised from a generator, terminates the generator
jfj
Peter Otten wrote: To confuse a newbies and old hands alike, Bengt Richter wrote:
Need something more straightforward , e.g., a wrapped one-liner:
>>> def guess(n=3): print ("You're right!", 'No more tries for >>> you!!!')[n-1 in ... (x for x in xrange(n) for t in [raw_input('Gues s my name: ')=='Ben'] ... if not t or iter([]).next())] ... >>> guess() To make it a bit clearer, a StopIteration raised in a generator
expression silently terminates that generator: def stop(): raise StopIteration ... list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]
In a list comprehension, on the other hand, it is propagated: [i for i in range(10) if i < 5 or stop()] Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 1, in stop StopIteration
Is that an intentional difference?
Very interesting. I'm not sure if the designers even considered this
particular subtlety. Why it happens is pretty plain. In the generator
expression case, the generator expression does propogate the
StopIteration, but list() traps it. List comprehensions are internally
treated as a for-loop (kind of), which doesn't trap StopIteration.
Maybe it should.
The list comprehension [ x for x in y ] is currently treated as
equivalent to the following, with byte-code optimizations:
.. _ = []
.. for x in y:
.. _.append(x)
Perhaps it ought to be equivalent to:
.. _ = []
.. try:
.. for x in y:
.. _.append(x)
.. except StopIteration:
.. pass
However, I would guess the Python gods wouldn't approve of this use of
StopIteration, and so would make no sacrifices to get it.
Nevertheless, it seems likely to be how a list comprehension would
behave in Python 3.0, so maybe we should do it.
--
CARL BANKS
[Peter Otten] a StopIteration raised in a generator expression silently terminates that generator:
def stop(): raise StopIteration ... list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]
In a list comprehension, on the other hand, it is propagated: [i for i in range(10) if i < 5 or stop()]
Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 1, in stop StopIteration
Is that an intentional difference?
I would call it an unfortunate assymmetry -- one the never comes up unless
you're up to no good ;-)
In a way, both behave identically. They both raise StopIteration. In the case
of the generator expression, that StopIteration is intercepted by the enclosing
list() call. That becomes obvious if you write a pure python equivalent for
list:
def lyst(s):
it = iter(s)
result = []
try:
while 1:
result.append(i t.next())
except StopIteration: # guess who trapped StopIter
return result
Raymond Hettinger
On Fri, 01 Apr 2005 16:34:32 GMT, "Raymond Hettinger" <vz******@veriz on.net> wrote: [Peter Otten] a StopIteration raised in a generator expression silently terminates that generator:
>>> def stop(): raise StopIteration ... >>> list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]
In a list comprehension, on the other hand, it is propagated:
>>> [i for i in range(10) if i < 5 or stop()] Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 1, in stop StopIteration
Is that an intentional difference?
I would call it an unfortunate assymmetry -- one the never comes up unless you're up to no good ;-)
;-) In a way, both behave identically. They both raise StopIteration. In the case of the generator expression, that StopIteration is intercepted by the enclosing list() call. That becomes obvious if you write a pure python equivalent for list:
def lyst(s): it = iter(s) result = [] try: while 1: result.append(i t.next()) except StopIteration: # guess who trapped StopIter return result
I assumed that all standard sequence consumers (including list, of course) would intercept
the StopIteration of a sequence given them in the form of a generator expression, so your
lyst example would have an analogue for other sequence consumers as well, right?
I.e., there's not a hidden list(genex) in those others I would hope ;-)
E.g., "in" in my toy exposed more clearly, using Peter's stop: def show(x): print x,; return x
... def stop(): raise StopIteration
... 2 in (x for x in xrange(5) if show(x)<4 or stop())
0 1 2
True 7 in (x for x in xrange(5) if show(x)<4 or stop())
0 1 2 3 4
False
BTW I notice that this also nicely shortcuts when the 2 is found.
Regards,
Bengt Richter
> I assumed that all standard sequence consumers (including list, of course)
would intercept the StopIteration of a sequence given them in the form of a generator
expression, so your lyst example would have an analogue for other sequence consumers as well,
right? I.e., there's not a hidden list(genex) in those others I would hope ;-)
Right.
E.g., "in" in my toy exposed more clearly, using Peter's stop:
>>> def show(x): print x,; return x ... >>> def stop(): raise StopIteration ... >>> 2 in (x for x in xrange(5) if show(x)<4 or stop()) 0 1 2 True >>> 7 in (x for x in xrange(5) if show(x)<4 or stop())
0 1 2 3 4 False
BTW I notice that this also nicely shortcuts when the 2 is found.
That's a fact.
Raymond
Raymond Hettinger wrote:
(quoting Bengt) I assumed that all standard sequence consumers (including list, of course) would intercept the StopIteration of a sequence given them in the form of a generator expression, so your lyst example would have an analogue for other sequence consumers as well, right? I.e., there's not a hidden list(genex) in those others I would hope ;-) Right.
I see I followed the historical evolvement and saw generator expressions as
a lazy listcomp rather than a cool new way to write a generator. That
turned out to be the road to confusion.
Thanks Carl, thanks Raymond for setting me straight.
I would call it an unfortunate assymmetry -- one the never comes up unless you're up to no good ;-)
Do you see any chance that list comprehensions will be redefined as an
alternative spelling for list(<generator expression>)?
Peter
jfj wrote: To make it a bit clearer, a StopIteration raised in a generator expression silently terminates that generator:
*any* exception raised from a generator, terminates the generator
Yeah, but StopIteration is the only expected exception and therefore the
only one that client code (nearly) always knows to deal with: def choke(): raise ValueError
.... list(i for i in range(10) if i < 3 or choke())
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in <generator expression>
File "<stdin>", line 1, in choke
ValueError [i for i in range(10) if i < 3 or choke()]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in choke
ValueError
Here you can *not* tell apart list(genexp) and listcomp.
(Of course, as has since been pointed out, the StopIteration is actually
caught in the list constructor, so nothing magic to the example in my
initial post)
Peter
[Peter Otten] Do you see any chance that list comprehensions will be redefined as an alternative spelling for list(<generator expression>)?
Not likely. It is possible that the latter spelling would make it possible for
Py3.0. eliminate list comps entirely. However, they are very popular and
practical, so my bet is that they will live on.
The more likely change is that in Py3.0 list comps will no longer expose the
loop variable outside the loop.
Raymond Hettinger
Raymond Hettinger wrote: [Peter Otten]
Do you see any chance that list comprehensions will be redefined as an alternative spelling for list(<generator expression>)?
Not likely. It is possible that the latter spelling would make it possible for Py3.0. eliminate list comps entirely. However, they are very popular and practical, so my bet is that they will live on.
I suspect you're right, but I certainly wouldn't complain if list comps
disappeared. TOOWTDI and all, and I often find myself alternating
between the two when I can't decide which one seems more Pythonic.
(These days I generally write a listcomp, but I wouldn't put any money
on my code being entirely consistent about this...)
STeVe This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Raymond Hettinger |
last post by:
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)
|
by: Mahesh Padmanabhan |
last post by:
Hi,
When list comprehension was added to the language, I had a lot of
trouble understanding it but now that I am familiar with it, I am not
sure how I programmed in Python without it.
Now I see that generator expressions have been added to the language
with 2.4 and I question the need for it. I know that it allows for lazy
evaluation which speeds things up for larger lists but why was it
necessary to add it instead of improving list...
|
by: Joh |
last post by:
hello,
i'm trying to understand how i could build following consecutive sets
from a root one using generator :
l =
would like to produce :
, , , ,
|
by: malcolm |
last post by:
Example, suppose you have these 2 tables
(NOTE: My example is totally different, but I'm simply trying to setup
the a simpler version, so excuse the bad design; not the point here)
CarsSold {
CarsSoldID int (primary key)
MonthID int
DealershipID int
NumberCarsSold int
|
by: aj70000 |
last post by:
This is my query
select ano,max(date),a_subject from MY_TAB where table_name='xyz' and
ano=877
group by a_subject,ano order by a_subject
ANO max(Date) A_Subject
877 2005-01-20 00:00:00.000 Subject_1
877 1900-01-01 00:00:00.000 Subject_2
877 2004-12-20 00:00:00.000 Subject_3
| |
by: bonono |
last post by:
Hi,
I initially thought that generator/generator expression is cool(sort of
like the lazy evaluation in Haskell) until I notice this side effect.
>>>a=(x for x in range(2))
>>>list(a)
>>>list(a)
|
by: Laurent Pointal |
last post by:
on win32]
Given the following:
45
....
(<generator object at 0x00A79788>,)
....
File "<stdin>", line 1
SyntaxError: invalid syntax
|
by: Kris Kowal |
last post by:
I had a thought that might be pepworthy. Might we be able to break
outer loops using an iter-instance specific StopIteration type?
This is the desired, if not desirable, syntax::
import string
letters = iter(string.lowercase)
for letter in letters:
for number in range(10):
print letter, number
|
by: ccy56781 |
last post by:
I'm writing to see calcuration process.
And so, I can't catch StopIteration...
What is mistake?
def collatz(n):
r=
while n>1:
r.append(n)
n = 3*n+1 if n%2 else n/2
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
| |
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |