[Python-ideas] A conditional "for" statement

4 views
Skip to first unread message

Michael S. Gilbert

unread,
Apr 23, 2009, 6:29:15 PM4/23/09
to python...@python.org
Hello,

I've recently been working on some code where i am processing a
list, but excluding certain items. The solution is to use a list
comprehension in the "for" statement. An example is:

for m in [n for n in range( 0 , 5 ) if n != 2]

Determining what's going on here isn't immediately obvious (i.e.
what's this new variable n doing?). It would be nice to have a more
streamlined syntax such as:

for m in range( 0 , 5 ) with m != 2

which is much cleaner and obvious. It is also very much like the
list comprehension syntax (although i've changed "if" to "with", and
the better of the two is subject to personal opinion and debatable). I
would hope that the statements following "with" could be any conditional
expression.

This is just a thought I had while working today. Thank you for your
consideration.

Best Regards,
Mike
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Chris Rebert

unread,
Apr 23, 2009, 6:34:58 PM4/23/09
to Michael S. Gilbert, python...@python.org
On Thu, Apr 23, 2009 at 3:29 PM, Michael S. Gilbert
<michael....@gmail.com> wrote:
> Hello,
>
> I've recently been working on some code where i am processing a
> list, but excluding certain items.  The solution is to use a list
> comprehension in the "for" statement.  An example is:
>
>  for m in [n for n in range( 0 , 5 ) if n != 2]
>
> Determining what's going on here isn't immediately obvious (i.e.
> what's this new variable n doing?).  It would be nice to have a more
> streamlined syntax such as:
>
>  for m in range( 0 , 5 ) with m != 2

I don't see how this is clearer than either of the obvious alternatives:

for m in range(0 , 5):
if m == 2:
continue
#loop body

for m in range(0 , 5):
if m != 2:
#loop body

It's certainly /slightly/ shorter, but the problem is not severe
enough to warrant new syntax, imho.
Also, this uses the `with` keyword in a completely different way from
its existing use, which could be confusing.

Cheers,
Chris
--
I have a blog:
http://blog.rebertia.com

Michael S. Gilbert

unread,
Apr 23, 2009, 6:49:29 PM4/23/09
to Chris Rebert, python...@python.org
On Thu, 23 Apr 2009 15:34:58 -0700, Chris Rebert wrote:
> I don't see how this is clearer than either of the obvious alternatives:

The purpose would also be efficiency. It's less efficient to check the
condition m==2 during every loop iteration than it is to set up a list
that excludes m=2 to begin with.

> It's certainly /slightly/ shorter, but the problem is not severe
> enough to warrant new syntax, imho.
> Also, this uses the `with` keyword in a completely different way from
> its existing use, which could be confusing.

Right, like I said, that's debatable, and "if" probably makes more
sense since it mimicks the list comprehension syntax anyway. Example:

for m in range( 0 , 5 ) if m != 2:
print m
vs

[m for m in range( 0 , 5 ) if m != 2 ]:

Mike

Terry Reedy

unread,
Apr 23, 2009, 6:56:28 PM4/23/09
to python...@python.org
Proposed and rejected.

The difference between

for i in seq:
if p(i):
do(i)

and

for i in seq if p(i):
do(i)

is deletion of ':\n'. Hardly worth the bother.

Michael S. Gilbert

unread,
Apr 23, 2009, 7:07:07 PM4/23/09
to Terry Reedy, python...@python.org
On Thu, 23 Apr 2009 18:56:28 -0400, Terry Reedy wrote:
> Proposed and rejected.
>
> The difference between
>
> for i in seq:
> if p(i):
> do(i)
>
> and
>
> for i in seq if p(i):
> do(i)
>
> is deletion of ':\n'. Hardly worth the bother.

What about the difference in efficiency? For the second case, you've
reduced the number of iterations (by the number of items that your
conditional expression has excluded) and eliminated one operation per
iteration (evaluation the if statement).

Mike

Bruce Leban

unread,
Apr 23, 2009, 7:19:13 PM4/23/09
to Michael S. Gilbert, python...@python.org, Terry Reedy
what makes you think that this would be more efficient? If it was significant, surely the compiler could detect the for/if idiom and optimize it.

Michael S. Gilbert

unread,
Apr 23, 2009, 7:40:16 PM4/23/09
to Mike Meyer, python...@python.org
On Thu, 23 Apr 2009 19:09:14 -0400, Mike Meyer wrote:
> If you believe this is still true (though as has been pointed out,
> this idea has already been considered and rejected), show us the
> timings. In particular, with a range of different values for the
> percentage of excluded elements: say 0, 10, 50, 90 and 100?

Ok, I'll admit when I'm wrong. It actually takes longer to use the
list comprehension (for all exclusion percentages), which, for me at
least, is completely unintuitive. For 1 million samples:

excluded: 0%, comprehension time: 0.840000
excluded: 0%, if time: 0.530000
excluded: 10%, comprehension time: 0.770000
excluded: 10%, if time: 0.520000
excluded: 20%, comprehension time: 0.710000
excluded: 20%, if time: 0.490000
excluded: 30%, comprehension time: 0.670000
excluded: 30%, if time: 0.460000
excluded: 40%, comprehension time: 0.610000
excluded: 40%, if time: 0.450000
excluded: 50%, comprehension time: 0.560000
excluded: 50%, if time: 0.420000
excluded: 60%, comprehension time: 0.510000
excluded: 60%, if time: 0.400000
excluded: 70%, comprehension time: 0.450000
excluded: 70%, if time: 0.380000
excluded: 80%, comprehension time: 0.410000
excluded: 80%, if time: 0.350000
excluded: 90%, comprehension time: 0.360000
excluded: 90%, if time: 0.330000
excluded: 100%, comprehension time: 0.310000
excluded: 100%, if time: 0.300000

I hereby accept the rejection of this idea since it makes sense neither
from a syntax nor efficiency point of view.

Best Regards,

Greg Ewing

unread,
Apr 23, 2009, 8:20:40 PM4/23/09
to Michael S. Gilbert, python...@python.org
Michael S. Gilbert wrote:

> What about the difference in efficiency? For the second case, you've
> reduced the number of iterations (by the number of items that your
> conditional expression has excluded) and eliminated one operation per
> iteration (evaluation the if statement).

No, you haven't. You still have to perform the test
for every iteration. Your proposed syntax would do
*exactly* the same thing as the 3-line version.

--
Greg

Greg Ewing

unread,
Apr 23, 2009, 8:22:10 PM4/23/09
to Michael S. Gilbert, python...@python.org
Michael S. Gilbert wrote:
> It actually takes longer to use the
> list comprehension (for all exclusion percentages), which, for me at
> least, is completely unintuitive.

The LC version is doing everything that the non-LC
version is doing, plus building a list. Doing more
work takes longer.

--
Greg

Ben Finney

unread,
Apr 23, 2009, 8:24:58 PM4/23/09
to python...@python.org
"Michael S. Gilbert"
<michael....@gmail.com> writes:

> The purpose would also be efficiency. It's less efficient to check the
> condition m==2 during every loop iteration than it is to set up a list
> that excludes m=2 to begin with.

Huh? “Set up the list” involves exactly the conditional check for each
item in the original sequence. So those condition checks for each item
in the original sequence are going to be paid anyway.

--
\ “bash awk grep perl sed, df du, du-du du-du, vi troff su fsck |
`\ rm * halt LART LART LART!” —The Swedish BOFH, |
_o__) alt.sysadmin.recovery |
Ben Finney

spir

unread,
Apr 24, 2009, 6:07:05 AM4/24/09
to python...@python.org
Le Thu, 23 Apr 2009 18:29:15 -0400,
"Michael S. Gilbert" <michael....@gmail.com> s'exprima ainsi:

> Hello,
>
> I've recently been working on some code where i am processing a
> list, but excluding certain items. The solution is to use a list
> comprehension in the "for" statement. An example is:
>
> for m in [n for n in range( 0 , 5 ) if n != 2]
>
> Determining what's going on here isn't immediately obvious (i.e.
> what's this new variable n doing?). It would be nice to have a more
> streamlined syntax such as:
>
> for m in range( 0 , 5 ) with m != 2

Should be 'if' anyway; certainly not 'with', anyway.

> which is much cleaner and obvious.

Actually, I see the syntactic issue differently. I applies to lambdas as well as list comps (that, in fact, also implicitely define unnamed funcs).
Often filtering or mapping expressions are straightforward operations on the items, so that the whole construct needed seems heavy redundance:
[n for n in numbers if n!=2]
filter(numbers, lambda n: n!=2)

What we would like to express is only the "operational" part of the expression:
[numbers if !=2]
filter(numbers, !=2)
This would be nice as well for a swtich-like statement:
swith on x:
case == 0: ...
case < 0: ...
case > 0: ...
else: ;-)

But this is (imo elegant) postfix syntax that allows omitting parameters using an implicit value stack, but does not fit in python, I guess.
def half: return 2 /
def square: return dup *
def sum: return +
The price to pay is difficult stack juggling as soon as operations are not trivial.

What I would certainly like is restricting the field of anonymous func expression (in both lambdas and list comps) to these trivial cases -- so that we could then omit parameters/items using postfix syntax. Otherwise use a defined func wich implicit parameter is the item.
Of course the drawback is that expressions of very low level of complication would have to be defined in a func:
def hasValidValue(result):
return result.value is not None
validResults = [results if hasValidValue]
But we may allow attribute syntax:
noneResults = [results if .value]

> Best Regards,
> Mike


Denis
------
la vita e estrany

Reply all
Reply to author
Forward
0 new messages