Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > [ x for x in xrange(10) when p(x) ]

Reply
Thread Tools

[ x for x in xrange(10) when p(x) ]

 
 
Alex Martelli
Guest
Posts: n/a
 
      11-10-2005
<> wrote:

> I use "list" in the name in "english"/general sense(say a list in
> haskell is lazily evaluated), it could be a list or it could be a
> lazily evaluated iterable.


OK, but the general point is:
[x for x in <whatever>] is best written list(<whatever>)
(x for x in <whatever>) is best written iter(<whatever>)
(and if <whatever> is already a list and doesn't need to be copied, or
respectively is already being iterated on, just <whatever>).


> The original post is really just about "when" or may be "until" syntax
> that makes it a bit shorter to read and hopefuly easier to understand.


This is the first time on this thread in which I'm glimpsing that you
mean 'when' not as in SQL (where it has just the same meaning as the
'if' in Python's genexps/listcomps), but rather with the meaning that
any Pythonista would instinctively spell 'while'. Since AFAIK 'when' is
only used in SQL (out of widespread languages), using it with a
drastically different meaning would be an utter disaster, IMHO.

Right now, listcomps and genexps can be explained very simply as
equivalent to just the same nesting of for and if statement as they have
clauses in sequence. Adding a 'while' clause (or 'until', etc) would
unfortunately break this simple rule, and therefore make the whole
construct harder, not easier, to understand. Unless there are very
compelling and frequent use cases for such an addition, I doubt it's
worth even trying to make a patch in order to time it against
itertools.takewhile...


Alex
 
Reply With Quote
 
 
 
 
Alex Martelli
Guest
Posts: n/a
 
      11-10-2005
<> wrote:
...
> takewhile(lambda x: condition(x), some_generator) is not very much
> difference than(well, still more things to type)
>
> (x for x in some_generator when condition(x))


So use takewhile(condition, some_generator)

which is LESS to type. When your predicate is a function, there's no
need to wrap a lambda around it, just like there's no need to wrap an
'[x for x in' or '(x for x in' around a list/iterator.


> but when I have a number of them in the same expression, the
> takewhile/dropwhile becomes to add up.


Complicated expressions often become hard to read; so, break the
expression up into more readable pieces, assigning names to the
intermediate steps. There's negligible price to pay for that, since in
Python assignment is NOT a copy, just a 'naming' of an intermediate
object. For example, instead of:

for x in takefile(foo, takewhile(bar, zlupp)): ...

you may choose to code, e.g.,

zlupps_bars = takewhile(bar, zlupp)
zb_foos = takewhile(foo, zlupps_bars)
for x in zb_foos: ...

Flat is better than nested.
Sparse is better than dense.
Readability counts.


Alex
 
Reply With Quote
 
 
 
 
bonono@gmail.com
Guest
Posts: n/a
 
      11-10-2005

Alex Martelli wrote:
> This is the first time on this thread in which I'm glimpsing that you
> mean 'when' not as in SQL (where it has just the same meaning as the
> 'if' in Python's genexps/listcomps), but rather with the meaning that
> any Pythonista would instinctively spell 'while'. Since AFAIK 'when' is
> only used in SQL (out of widespread languages), using it with a
> drastically different meaning would be an utter disaster, IMHO.

The original post was in the context about dropwhile/takewhile. I may
choose the wrong word "when". BTW, what does "when" do it SQL ? I only
know about "where" which I believe is the closest equvialent of "if" in
python generator comprehension/list expression.

To me when/while has a "sequence" element there whereas "where/if"
don't. I didn't choose "while" because I know it is a key word already
in python so I never thought about it being in this kind of construct,
but thinking about it, "if" can be used in list expression then may be
while can be used to.

>
> Right now, listcomps and genexps can be explained very simply as
> equivalent to just the same nesting of for and if statement as they have
> clauses in sequence. Adding a 'while' clause (or 'until', etc) would
> unfortunately break this simple rule, and therefore make the whole
> construct harder, not easier, to understand. Unless there are very
> compelling and frequent use cases for such an addition, I doubt it's
> worth even trying to make a patch in order to time it against
> itertools.takewhile...

I have no idea what it is involved or what about rules. I just raised a
simple question because the whole dropping filter/map/reduce discussion
I read gave me the impression that python is siding over in-line
list/generator expression rather than the more traditional
map/reduce/takewhile function call style.

 
Reply With Quote
 
bonono@gmail.com
Guest
Posts: n/a
 
      11-10-2005

Alex Martelli wrote:
> So use takewhile(condition, some_generator)
>
> which is LESS to type. When your predicate is a function, there's no
> need to wrap a lambda around it, just like there's no need to wrap an
> '[x for x in' or '(x for x in' around a list/iterator.

No. my predicate sometimes is not function but inline expression that
needs scoping within nested for.

> Complicated expressions often become hard to read; so, break the
> expression up into more readable pieces, assigning names to the
> intermediate steps. There's negligible price to pay for that, since in
> Python assignment is NOT a copy, just a 'naming' of an intermediate
> object. For example, instead of:
>
> for x in takefile(foo, takewhile(bar, zlupp)): ...
>
> you may choose to code, e.g.,
>
> zlupps_bars = takewhile(bar, zlupp)
> zb_foos = takewhile(foo, zlupps_bars)
> for x in zb_foos: ...
>
> Flat is better than nested.
> Sparse is better than dense.
> Readability counts.
>

That is one opinion and I think I can decide when to break or not to
break. Sometimes, breaking them in mutiple level for with interim name
assignment is not desirable. In fact, because python allows me to write
in both style, I practiced to write the same thing in both style and
found that the nested list expression way is less error prone(at least
for me ).

 
Reply With Quote
 
Colin J. Williams
Guest
Posts: n/a
 
      11-10-2005
Alex Martelli wrote:
> George Sakkis <> wrote:
> ...
>
>>>>FP functions like dropwhile/takewhile etc.
>>>
>>>No way -- the itertools module is and remains a PRECIOUS resource.
>>>If you want an iterator rather than a list, itertools.ifilter is quite
>>>appropriate here.

>>
>>What about the future of itertools in python 3K ? IIRC, several
>>functions and methods that currently return lists are going to return
>>iterators. Could this imply that itertools.(imap/ifilter/izip) will
>>take the place of map/filter/zip as builtins ?

>
>
> I think the builtin namespace shouldn't get too crowded. But what I
> think matters little -- what __GvR__ thinks is more important...!-)
>
>
> Alex

Are there generally accepted guidelines on what is appropriate for the
builtin namespace?

Colin W.
 
Reply With Quote
 
Bengt Richter
Guest
Posts: n/a
 
      11-10-2005
On 10 Nov 2005 04:56:34 -0800, "" <> wrote:

>
>Peter Hansen wrote:
>> (I say "readable or somehow better" since you stated in another post "I
>> just try to use list/generator expression when possible" but you didn't
>> explain your reason for doing so. I assume you have some reason other
>> than arbitrary whim.)

>The reason is simple:
>
>I found it easier to read for me and using list/generator expression
>helped me uncover a number of subtle bugs comparing with an imperative
>approach.
>
>on its own :
>
>takewhile(lambda x: condition(x), some_generator) is not very much
>difference than(well, still more things to type)
>
>(x for x in some_generator when condition(x))

I wish you wouldn't write "when" like that, as if it were legal python python syntax.
(Nor do I like guessing what it's supposed to mean

>>> list (x for x in xrange(20) when x<5))

File "<stdin>", line 1
list (x for x in xrange(20) when x<5))
^
SyntaxError: invalid syntax

If you want to terminate a generator expression after the first sequence of elements
satisfying a condition, and you don't want to use takewhile, I don't know of a gotcha
to prevent you from just raising StopIteration, using an expression that will do that, e.g.,

>>> list (x for x in xrange(20) if x<5 or iter([]).next())

[0, 1, 2, 3, 4]

Or a bit more readably:
>>> def stop(): raise StopIteration

...
>>> list (x for x in xrange(20) if x<5 or stop())

[0, 1, 2, 3, 4]

IOW, your "when condition(x)" (IIUIC) can be spelled "if condition(x) or stop()"

>
>but when I have a number of them in the same expression, the
>takewhile/dropwhile becomes to add up.

If you don't like Alex'(s?) good advice, you can continue bracketed expressions
on several lines, and indent and group for clarity.

Regards,
Bengt Richter
 
Reply With Quote
 
bonono@gmail.com
Guest
Posts: n/a
 
      11-11-2005

Bengt Richter wrote:
> If you want to terminate a generator expression after the first sequence of elements
> satisfying a condition, and you don't want to use takewhile, I don't know of a gotcha
> to prevent you from just raising StopIteration, using an expression that will do that, e.g.,
>
> >>> list (x for x in xrange(20) if x<5 or iter([]).next())

> [0, 1, 2, 3, 4]
>
> Or a bit more readably:
> >>> def stop(): raise StopIteration

> ...
> >>> list (x for x in xrange(20) if x<5 or stop())

> [0, 1, 2, 3, 4]
>
> IOW, your "when condition(x)" (IIUIC) can be spelled "if condition(x) or stop()"

If it is a single loop, takewhile/dropwhile is perfectly fine but as I
mentioned in another post, it is nested and the condition needs
surrounding scope so seperate function and StopIteration doesn't work
as it breaks out of the whole thing expression.

takewhile/dropwhile still works in this case(because of the lambda
which sees the surrounding scope).

 
Reply With Quote
 
Alex Martelli
Guest
Posts: n/a
 
      11-11-2005
<> wrote:

> > >>> list (x for x in xrange(20) if x<5 or iter([]).next())

> > [0, 1, 2, 3, 4]
> >
> > Or a bit more readably:
> > >>> def stop(): raise StopIteration

> > ...
> > >>> list (x for x in xrange(20) if x<5 or stop())

> > [0, 1, 2, 3, 4]
> >
> > IOW, your "when condition(x)" (IIUIC) can be spelled "if condition(x) or
> > stop()"

> If it is a single loop, takewhile/dropwhile is perfectly fine but as I
> mentioned in another post, it is nested and the condition needs
> surrounding scope so seperate function and StopIteration doesn't work
> as it breaks out of the whole thing expression.


Can you give one example where this stop() function wouldn't work and
your hypothetical ``when'' would? I don't see how "it breaks out of the
whole thing expression" -- it terminates ONE for-clause (and what else
would your cherished ``when'' do?).


Alex
 
Reply With Quote
 
bonono@gmail.com
Guest
Posts: n/a
 
      11-11-2005
oops, stand corrected. I was under the impression that an exception
would break out of the current expression and forgot that the "for"
would contain it(that StopIteration is a condition to it expects to
stop it).

thanks, this is the functionality I am looking for.

Alex Martelli wrote:
> Can you give one example where this stop() function wouldn't work and
> your hypothetical ``when'' would? I don't see how "it breaks out of the
> whole thing expression" -- it terminates ONE for-clause (and what else
> would your cherished ``when'' do?).
>
>
> Alex


 
Reply With Quote
 
bonono@gmail.com
Guest
Posts: n/a
 
      11-11-2005

Bengt Richter wrote:
> IOW, your "when condition(x)" (IIUIC) can be spelled "if condition(x) or stop()"

neat trick.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57