By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,977 Members | 1,369 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,977 IT Pros & Developers. It's quick & easy.

For loop extended syntax

P: n/a
I'm sure there must have been a past thread about this topic but I don't know how to find it: How
about extending the "for <X> in" syntax so that X can include default arguments ? This would be very
useful for list/generator comprehensions, for example being able to write something like:

[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]

instead of the less elegant explicit loop version that has to check for the length of each sequence.
What do you think ?

George
Jul 18 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
George Sakkis wrote:
This would be very
useful for list/generator comprehensions, for example being able to write something like:
[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]


Looks very appealing, but what to do with

[x*y-z for (x=0,y,z) in (1,2,3), (4,5), (6,7,8)] ?

Should it raise an exception due to a pattern mismatch?

If not how should matching rules apply here?

[x*y-z for (x=0,y=0,z=0) in (1,2,3), (4,5), (6,7,8)]

If in doubt write a vector class that cares about the correct padding (
or more general and with geometric meaning: select the right hyperplane
) and enable to switch between different paddings. This solution is
both flexible and reusable.

Regards Kay

Jul 18 '05 #2

P: n/a
George Sakkis wrote:
I'm sure there must have been a past thread about this topic but I don't know how to find it: How
about extending the "for <X> in" syntax so that X can include default arguments ? This would be very
useful for list/generator comprehensions, for example being able to write something like:

[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]

instead of the less elegant explicit loop version that has to check for the length of each sequence.
What do you think ?


How did you get the data in that format in the first place? It looks a
bit strange to me. Wouldn't it be easier to fill in default values when
you gather data as opposed to when you use it?

--
Ciao,
Matteo
Jul 18 '05 #3

P: n/a
"Kay Schluehr" <ka**********@gmx.net> wrote:
George Sakkis wrote:
This would be very
useful for list/generator comprehensions, for example being able to write something like:

[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]


Looks very appealing, but what to do with

[x*y-z for (x=0,y,z) in (1,2,3), (4,5), (6,7,8)] ?

Should it raise an exception due to a pattern mismatch?


I didn't have in mind to generalize the syntax even more than the respective for function
signatures, therefore this would be syntax error:
SyntaxError: non-keyword arg after keyword arg
If not how should matching rules apply here?

[x*y-z for (x=0,y=0,z=0) in (1,2,3), (4,5), (6,7,8)]

If in doubt write a vector class that cares about the correct padding (
or more general and with geometric meaning: select the right hyperplane
) and enable to switch between different paddings. This solution is
both flexible and reusable.

Regards Kay


This was just an example; I think the proposed functionality will be helpful in far more cases than
dealing with geometry or vectors, so I would prefer it to be supported by the language itself.

Regards,
George
Jul 18 '05 #4

P: n/a
"Matteo Dell'Amico" <de***@toglimi.linux.it> wrote:
George Sakkis wrote:
I'm sure there must have been a past thread about this topic but I don't know how to find it: How about extending the "for <X> in" syntax so that X can include default arguments ? This would be very useful for list/generator comprehensions, for example being able to write something like:

[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]

instead of the less elegant explicit loop version that has to check for the length of each sequence. What do you think ?


How did you get the data in that format in the first place? It looks a
bit strange to me. Wouldn't it be easier to fill in default values when
you gather data as opposed to when you use it?


Not always. Say for example that you're doing some 2D geometry stuff, and later you have to extend
it to 3D. In this case you may have to deal with both 2D and 3D objects, and map the former to the
latter when necessary.

George
Jul 18 '05 #5

P: n/a
On Sunday 20 March 2005 20:47, George Sakkis wrote:
Not always. Say for example that you're doing some 2D geometry stuff, and
later you have to extend it to 3D. In this case you may have to deal with
both 2D and 3D objects, and map the former to the latter when necessary.


But this rather sounds like you'd want an adaptor iterator, like the
following:
class AdaptPossible2D(object): ... def __init__(self,data):
... self.data = data
... def __iter__(self):
... for item in self.data:
... if len(item) == 2:
... yield item+(0,)
... else:
... yield item
... for x,y,z in AdaptPossible2D([(1,2),(1,2,3),(3,4)]):

... print x,y,z
...
1 2 0
1 2 3
3 4 0

Using the above code makes it absolutely clear what you want, and doesn't need
any new syntax which can be ambiguous like (x=0,y,z=0), etc. The above idiom
also takes only constant extra space, as it doesn't duplicate the list during
iteration.

--
--- Heiko.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBCPeapf0bpgh6uVAMRApwVAJ4hFU9cpP74rz4bBqzG4h c0Q62BGwCaAmWM
QPtnrQHixbzh2BlQcO27g0w=
=XEQp
-----END PGP SIGNATURE-----

Jul 18 '05 #6

P: n/a
"Heiko Wundram" <mo*******@ceosg.de> wrote in message
news:ma*************************************@pytho n.org...

On Sunday 20 March 2005 20:47, George Sakkis wrote:
Not always. Say for example that you're doing some 2D geometry stuff, and
later you have to extend it to 3D. In this case you may have to deal with
both 2D and 3D objects, and map the former to the latter when necessary.


But this rather sounds like you'd want an adaptor iterator, like the
following:
class AdaptPossible2D(object): ... def __init__(self,data):
... self.data = data
... def __iter__(self):
... for item in self.data:
... if len(item) == 2:
... yield item+(0,)
... else:
... yield item
... for x,y,z in AdaptPossible2D([(1,2),(1,2,3),(3,4)]):

... print x,y,z
...
1 2 0
1 2 3
3 4 0

Using the above code makes it absolutely clear what you want, and doesn't need
any new syntax which can be ambiguous like (x=0,y,z=0), etc. The above idiom
also takes only constant extra space, as it doesn't duplicate the list during
iteration.

Once more, the 2D/3D example was just that, an example; my point was not to find a specific solution
to a specific problem. Extending the "for .. in" syntax would be an elegant way to express this idea
in a more succint, familiar and generic way than a customized adaptor. As for the ambiguity, it is
not more ambiguous than function signatures as long as all keyword arguments go after all the
required ones; I'm not suggesting that (x=0,y,z=0) should be valid.

George
Jul 18 '05 #7

P: n/a
Am Sonntag, 20. März 2005 22:22 schrieb George Sakkis:
Once more, the 2D/3D example was just that, an example; my point was not to
find a specific solution to a specific problem.


And my point being: it's simple enough to give a general recipe (which my
example was) without extending Python's syntax, so why extend the syntax and
not just use a solution derived from that recipe that's working now (and is
backwards compatible at least to 2.3), and which is also clear in itself?

I'm not saying that your syntax looks "strange" or "bad", but there are means
to do what you want to do now, without cumbersome syntax or duplicating code,
and as such I'm -1 on syntactic sugar (TOWTDI and all)...

Don't take this the wrong way, but I think introducing syntax is the wrong
solution to a non-existant problem with the language.

--
--- Heiko.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBCPfsTf0bpgh6uVAMRAoxEAJ4j6ElTORU6UfghgvugsY 7hgZXSgQCfXA6Z
fGuqEyU2FCS+xhJN5i7kiKw=
=DNPb
-----END PGP SIGNATURE-----

Jul 18 '05 #8

P: n/a
"Heiko Wundram" <mo*******@ceosg.de> wrote:
Am Sonntag, 20. März 2005 22:22 schrieb George Sakkis:
Once more, the 2D/3D example was just that, an example; my point was not to
find a specific solution to a specific problem.


And my point being: it's simple enough to give a general recipe (which my
example was) without extending Python's syntax, so why extend the syntax and
not just use a solution derived from that recipe that's working now (and is
backwards compatible at least to 2.3), and which is also clear in itself?

I'm not saying that your syntax looks "strange" or "bad", but there are means
to do what you want to do now, without cumbersome syntax or duplicating code,
and as such I'm -1 on syntactic sugar (TOWTDI and all)...

Don't take this the wrong way, but I think introducing syntax is the wrong
solution to a non-existant problem with the language.


The way I see it, it's closer to applying existing syntax (from function signatures) in a new
context than introducing new syntax, but that's a detail. I guess it's a matter of personal
preference to syntactic sugar then. Still, python is rife with syntactic sugar: iterators, default
function arguments, *varargs, **kwdargs,[list]/(tuple)/{dict} literals, recently @decorators, and
more. If syntactic sugar didn't matter, we would be happy with scheme's syntax.

George
Jul 18 '05 #9

P: n/a
George Sakkis wrote:
Looks very appealing, but what to do with

[x*y-z for (x=0,y,z) in (1,2,3), (4,5), (6,7,8)] ?

Should it raise an exception due to a pattern mismatch?
I didn't have in mind to generalize the syntax even more than the

respective for function
signatures, therefore this would be syntax error:
SyntaxError: non-keyword arg after keyword arg


O.K. Allthough it has fallen out of Guidos favor one can use a lambda
to obtain the same solution:

[(lambda x,y,z=0:x*y-z)(*vec) for vec in (1,2,3), (4,5), (6,7,8)]

This inspires to examine Your list comprehension not as plain 'syntax
suggar' but in a clear operational perspective. Since (x,y,z=0) is not
a valid Python tuple we have to replace it by

lambda x,y,z=0:(x,y,z)

This acts on the list elements of the comprehension like the proposed
(x,y,z=0) whereas the valid (x,y,z) acts like

lambda x,y,z:(x,y,z)

So we have generalized tuples to lambdas. If we let lambda
x,y,z=0:(x,y,z) iterate over the list elements, why not the generalized

lambda x,y,z=0:(lambda x,a=0:(x,a),y,z) ?

Returning to Your soluion and translating back the lambda:

[x*y-z for ((x,a=0),y,z=0) in (1,2,3), (4,5), (6,7,8)]

should also be possible from an operational perspective.

Regards Kay

Jul 18 '05 #10

P: n/a
Ron
On Sun, 20 Mar 2005 13:16:37 -0500, "George Sakkis"
<gs*****@rutgers.edu> wrote:
I'm sure there must have been a past thread about this topic but I don't know how to find it: How
about extending the "for <X> in" syntax so that X can include default arguments ? This would be very
useful for list/generator comprehensions, for example being able to write something like:

[x*y-z for (x,y,z=0) in (1,2,3), (4,5), (6,7,8)]

instead of the less elegant explicit loop version that has to check for the length of each sequence.
What do you think ?

George


How would this examples work?

for x=5,y,z in (123),(4,5),(6,7,8,9)

Would the x default over ride the first value?
Should, the 4 element in the third tuple be dropped without an error?
A general reusable function might be something like this:

def formatlistofargs(arglist, nargs=1, defvalue=0):
returnvalues = []
for i in arglist:
ii = list(i)
while len(ii)<nargs:
ii.append(defvalue)
ii=ii[:nargs]
returnvalues.append(ii)
return returnvalues

for x,y,z in formatlistofargs(((1,2,3),(3,4),(5,6,7,8)),3):
print x,y,z
Ron

Jul 18 '05 #11

P: n/a
"Ron" <ra****@tampabay.rr.com> wrote:
How would this examples work?

for x=5,y,z in (123),(4,5),(6,7,8,9)

Would the x default over ride the first value?
Should, the 4 element in the third tuple be dropped without an error?
It has already been clarified twice in the thread that the default values would be allowed *only in
the end*, exactly as default function arguments.
A general reusable function might be something like this:

def formatlistofargs(arglist, nargs=1, defvalue=0):
returnvalues = []
for i in arglist:
ii = list(i)
while len(ii)<nargs:
ii.append(defvalue)
ii=ii[:nargs]
returnvalues.append(ii)
return returnvalues

for x,y,z in formatlistofargs(((1,2,3),(3,4),(5,6,7,8)),3):
print x,y,z


Of course there are ways to have a function fill in the defaults, but syntactically I would find
"for (x,y,z=0) in (1,2,3), (4,5), (6,7,8): print x,y,z" more obvious and concise.

By the way, I don't think it's a good idea in general to drop the extra values implicitly, as you do
in your recipe, for the same reason that calling a function foo(x,y,z) as foo(1,2,3,4) is an error.
A generalization of the 'for .. in' syntax that would handle extra arguments the same way as
functions would be:

for (x,y,z=0,*rest) in (1,2,3), (3,4), (5,6,7,8):
print x, y, z, rest

I'd love to see this in python one day; it is pretty obvious what it would do for anyone familiar
with function argument tuples.

George
Jul 18 '05 #12

P: n/a
George Sakkis wrote:
A generalization of the 'for .. in' syntax that would handle
extra arguments the same way as functions would be:

for (x,y,z=0,*rest) in (1,2,3), (3,4), (5,6,7,8):
print x, y, z, rest

I'd love to see this in python one day; it is pretty obvious what
it would do for anyone familiar with function argument tuples.


Let's all keep in mind that for...in... is using standard tuple
unpacking rules (you're getting the next tuple from a list of tuples,
and then unpacking that tuple), so what is really being proposed are
extensions to tuple unpacking. (Making this work in the context of a
for loop but not work in other tuple-unpacking situations would create
inconsistency.)

Function arguments are *not* (in general) a case of tuple unpacking,
on the other hand, so the parallels between function arguments and for
loop control-variable tuples are not so straightforward as is being
claimed.

There may be valid arguments in favor of enhancing tuple unpacking in
this way (indeed, I believe I recall a thread or two on this subject),
but it's important to consider the general consequences, not just the
single aspect of for-loop usage.

Jeff Shannon

Jul 18 '05 #13

P: n/a

"George Sakkis" <gs*****@rutgers.edu> wrote in message
news:3a*************@individual.net...
A generalization of the 'for .. in' syntax that would handle
extra arguments the same way as functions would be:

for (x,y,z=0,*rest) in (1,2,3), (3,4), (5,6,7,8):
print x, y, z, rest

I'd love to see this in python one day; it is pretty obvious
what it would do for anyone familiar with function argument tuples.


Jeff covered the obvious objection that this is a change from assignment
sematics to function call semantics. Slightly less obvious is that this
will slow down everyone's for loops for the benefit of the very few who
would want to do such a thing. (Is the above based on a real use case?)
Python function calls are 'slow' (relative to assignment, certainly) in
part *because* of the great flexibility in call signatures.

In any case, one can now write (with hardcoded format and types, untested):

def argify(*tups):
for tup in tups:
ltup = len(tup)
if ltup >= 4: yield tup[0:3] + (tup[3:],)
elif ltup == 3: yield tup + ((),)
elif ltup == 2: yield tup + (0, ())
else: raise TypeError("Tuple %s needs at least 2 items"
% (tup,)

for x,y,z,rest in argify(....): print x,y,x,rest

Terry J. Reedy

Jul 18 '05 #14

P: n/a
Jeff Shannon wrote:
Function arguments are *not* (in general) a case of tuple unpacking, on
the other hand, so the parallels between function arguments and for loop
control-variable tuples are not so straightforward as is being claimed.


It seems to me the parallel is close enough that no
confusion would result.

Can you think of any situation in which surprising
behaviour would occur through someone thinking the
parallel was closer than it is?

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

P: n/a
Ron
On Mon, 21 Mar 2005 15:56:26 -0500, "George Sakkis"
<gs*****@rutgers.edu> wrote:

It has already been clarified twice in the thread that the default values would be allowed *only in
the end*, exactly as default function arguments.
Was just asking if there should be other special general cases. What
programmers want usually depend on the problem at hand. imho :)
Of course there are ways to have a function fill in the defaults, but syntactically I would find
"for (x,y,z=0) in (1,2,3), (4,5), (6,7,8): print x,y,z" more obvious and concise.

By the way, I don't think it's a good idea in general to drop the extra values implicitly, as you do
in your recipe, for the same reason that calling a function foo(x,y,z) as foo(1,2,3,4) is an error.
A generalization of the 'for .. in' syntax that would handle extra arguments the same way as
functions would be:

for (x,y,z=0,*rest) in (1,2,3), (3,4), (5,6,7,8):
print x, y, z, rest

I'd love to see this in python one day; it is pretty obvious what it would do for anyone familiar
with function argument tuples.

George


I would probably do it this way myself:

def padlist(alist,length,pad):
alist[length:]=[pad]*(length-len(alist))
return alist

for xyz in [1,2,3],[3,4],[5,6,7]:
x,y,z = padlist(xyz, 3, 0)
print x,y,z

# or this if it's faster:

for x,y,z in [padlist(xyz,3,0) for xyz in [1,2,3],[3,4],[5,6,7]]:
print x,y,z
Which isn't too different from what you are suggesting. I think
someone may have already suggested using list comprehensions.

Ron


Jul 18 '05 #16

P: n/a
Terry Reedy wrote:
Jeff covered the obvious objection that this is a change from assignment sematics to function call semantics.
Slightly less obvious is that this
will slow down everyone's for loops for the benefit of the very few who would want to do such a thing.


If the action of (x,y,z=0) on a tuple is regarded as a function call
why not letting resolve it by the compiler in an appropriate manner?
The tuple assignment is just a special case of this and can be resolved
in a different way. There would be no slowdown at all.

Regards Kay

Jul 18 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.