Python 2.4 | 7.3 The for statement

B

brainsucker

Hi My name is Juan Carlos Rodrigo, and I love Python.
It is the most impressive and usefull language that
I have ever seen.

I am studing, at http://www.uoc.edu, an Information
Technology Postgraduate. And I have programmed some
REXX applications in my past Jobs (So I love python,
no more ENDS).

** Reposting from Python-Dev with some more comments.

--------8<--------8<--------8<--------8<--------8<--------8<--------

Python 2.4 | 7.3 The for statement:
-----------------------------------

for_stmt ::= "for" target_list "in" expression_list ":"
suite ["else" ":" suite]


New for statement:
------------------

for_stmt ::= "for" target_list "in" expression_list
[ "and" expression ] ":"
suite ["else" ":" suite]

** If the expression evaluates to False before
entering the for, jump else.
** If the expression is evaluated to False after
the first iteration, break.


So ¿What we can do with this new for?,
and ¿It is going to avoid line exceed?:

"My second remark is that our intellectual powers are rather
geared to master static relations and that our powers to
visualize processes evolving in time are relatively poorly
developed." [1]


It is easier if we see it beforehand:
-------------------------------------

leave = False
alist = [1,2,3,3,4,5,6,7,8,9]
for item in alist and not leave:
if item is 1: leave = True


Avoiding code exceed:
---------------------

a = 1
b = 2
c = 3
alist = [1,2,3,4,5,6,7,8,9]
for item in alist and a < 2 and b < 3 and c < 4:
if item == 3: a += 1
if item == 2: b += 1
if item == 1: c += 1
print "%d %d %d" % (a,b,c)
# three lines off (25% less on breaks)


Other features and the else:
----------------------------

alist = [1,2,3]
enter = False
if list[0] == 4:
enter = True
for item in alist and enter:
print item
else:
print "No account"


The real problem:
-----------------

"The exercise to translate an arbitrary flow diagram more or
less mechanically into a jump-less one, however, is not to be
recommended." [1]

Ok, it's not recommended, at large, but Python should make it possible,
and then the people will choose.


[1] Go To Statement Considered Harmful
Edsger W. Dijkstra
http://www.acm.org/classics/oct95/

PD: Your work is impressive, thanks.

--------8<--------8<--------8<--------8<--------8<--------8<--------

+++ Andrew Koenig said:
for_stmt ::= "for" target_list "in" expression_list
[ "and" expression ] ":"
suite ["else" ":" suite]
It can't work. The expression_list could be just a variable, as could the
expression, in which case you get
"for" target_list "in" variable "and" variable ":"

Considering that your for definition is not correct.
and, of course
variable "and" variable
is already an expression. So it's ambiguous.

No my definition has no ambiguity in it and your idea does
not work as you think, because is not an expression as you
incorrectly wrote out, is an expression_list:
leave = True
l = [1,2,3,4]
form item in l and leave:
File "<stdin>", line 1
form item in l and leave:

And your example what really does is iterating over the
expression_list (BTW: "and" cannot be used as you point out):
leave = True
l = [1,2,3,4]
for item in l, leave:
.... print item
....
[1, 2, 3, 4]
True


+++ Nick Coghlan said:
Interesting idea, but not really needed given the
existence of the break statement:
for item in alist:
if item is 1:
break

Well Nick the point here is to have the possibility
to leave for loops without using the break statement,
and of course use breaks too.


+++ Nick Coghlan said:
All non-sequential control structures are merely constrained ways of
using goto (the underlying machine code will devolve into conditional
and unconditional branches and jumps - i.e. goto's).

No doubt Nick, but were are programming on a very, very high level
language.

____________________________________________
'break' is a highly constrained form of goto and a fundamental part
of structured programming (as is 'continue')

Well you are expressing it better than I am.
I used to share your sentiment regarding break and continue -
experience (especially Python experience) has convinced me otherwise.
Python embraces the concept of breaking out of a loop to the point
that it even has an 'else' clause on loop structures that is executed
only if the loop is exited naturally rather than via a break
statement.

And It will be better with by for breaking possibilities.
Regardless of whether you personally choose to use break and
continue, the existence of those statements is the main reason
that the addition of a flag condition to for loops is highly
unlikely.

¿Why is that C has both break, continue and in for breaking
capabilities?

Thanks for your comments.
 
G

Guest

brainsucker said:
Python 2.4 | 7.3 The for statement:
-----------------------------------

for_stmt ::= "for" target_list "in" expression_list ":"
suite ["else" ":" suite]


New for statement:
------------------

for_stmt ::= "for" target_list "in" expression_list
[ "and" expression ] ":"
suite ["else" ":" suite]

** If the expression evaluates to False before
entering the for, jump else.
** If the expression is evaluated to False after
the first iteration, break.




I think that your idea is good but as others said the "and" literal
could be confusing. ¿Maybe we can use another word instead of "and"?

The for definition could be like this:

for_stmt ::= "for" target_list "in" expression_list
[ "until" expression ] ":"
suite ["else" ":" suite]

or some other word that clarifies the work of the expression

leave_cond_1 = False
leave_cond_2 = False
mylist = [1,2,3,4,5]
for item in mylist until leave_cond_1 or leave_cond_2:
print item
 
F

Facundo Batista

The for definition could be like this:

for_stmt ::= "for" target_list "in" expression_list
[ "until" expression ] ":"
suite ["else" ":" suite]

or some other word that clarifies the work of the expression

leave_cond_1 = False
leave_cond_2 = False
mylist = [1,2,3,4,5]
for item in mylist until leave_cond_1 or leave_cond_2:
print item

Still, this can be acomplished with the break statement, in a more
clear way, with less variables (which implies less work for the gc and
everybody).

In your example, instead of verifying some condition and setting
leave_cond_n to True, you just check the same condition, and use
break.

.. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://pyar.decode.com.ar/
 
B

brainsucker

Still, this can be acomplished with the break statement, in a more
clear way, with less variables (which implies less work for the gc and
everybody).

Glad to read from you Francisco. :) Keep up that hard work, thanks.

I have been talking with those Python programmers (And Role players),
:) and I have made a bit of code for you avoiding the "and" keyword:
cordure = 54
monster = [ "Tchulu", "Golum", "Cerberus"]
for wow in monster until cordure < 0:
if wow == "Tchulu": cordure -= 30
elif wow == "Cerberus": cordure -= 20
elif wow == "Golum": cordure -= 5
if cordure <= 0:
print "End game"
else:
print "Next task"


This is your version:
cordure = 54
monster = [ "Tchulu", "Golum", "Cerberus"]
for wow in monster:
if wow == "Tchulu": cordure -= 30
elif wow == "Cerberus": cordure -= 20
elif wow == "Golum": cordure -= 5
if cordure < 0: break # :|
if cordure <= 0:
print "End game"
else:
print "Next task"


a) As you can see, one more line of code...
Plus, in your code I do not see beforehand
when this roleplayer runs out of cordure.
# Little things matter. :)


b) Given that your IF condition is evaluated
ON every iteration, I see one line less on code,
evaluating the SAME conditions, for every
iteration.


c) I did not want to say this :|

+Debugging and friends:
+Tools > Search
+Break

ummmm in the new for I can see what is going
to happend beforehand, so I can search faster
when debugging:

"...our intellectual powers are rather
geared to master static relations..." [1]


d) I just wont more power on the just impressive
Python for loop, we can have it all.


[1] Go To Statement Considered Harmful
Edsger W. Dijkstra
http://www.acm.org/classics/oct95/



PD1: Francisco we have talked about this on the IRC,
the code presented is somehow TOY code to express
what I (Somebody?) want Python to do.

PD2: Try to imagine that nested loop with those
200+ lines in it ( Probably is bad coded :?, or not! )
and try to debug all those BREAKS.
 
D

Dennis Lee Bieber

cordure = 54
monster = [ "Tchulu", "Golum", "Cerberus"]
for wow in monster until cordure < 0:
if wow == "Tchulu": cordure -= 30
elif wow == "Cerberus": cordure -= 20
elif wow == "Golum": cordure -= 5
if cordure <= 0:
print "End game"
else:
print "Next task"
And that could be modified even further, using current
(unextended) Python...

Data structures are your friend...

-=-=-=-=-=-=-=-

monsterValue = { "Tchulu" : 30, #is this "cthulhu"?
"Cerberus" : 20,
"Golum" : 5 #wimp!
}

cordure = 56

for (m, c) in monsterValue.items(): #don't need m, actually
if cordure < 0: break
print m
cordure -= c

if cordure <= 0:
print "End Game!"
else:
print "Next Task"

# Using the dictionary allows for such things as:

strikes = [ "Golum", "Golum", "Tchulu",
"Golum", "Cerberus", "Golum" ]
cordure = 56

for m in strikes:
if cordure < 0 : break
print m
cordure -= monsterValue[m]

if cordure <= 0:
print "End Game!"
else:
print "Next Task"

-=-=-=-=-=-=-=-=-
G:\My Documents>python t.py
Golum
Tchulu
Cerberus
Next Task
Golum
Golum
Tchulu
Golum
Cerberus
End Game!

G:\My Documents>

--
 
B

brainsucker

And that could be modified even further, using current
(unextended) Python...

Nice code Wulfraed (or Dennis), back to the basics:

-- Your code
foo = 0
for item1 in range(10):
for item2 in range(10):
foo = item1 + item2
if foo == 2:
print "Let's see"
break # let's go
if (item1 + item2) == 2:
break # one more time
print foo

(7)
-- Another version
foo = 0
for item1 in range(10) until foo == 2:
for item2 in range(10) until foo == 2:
foo = item1 + item2
if foo == 2: print "Let's see"
print foo

# ~40% lines off on the n^2 breaking loop

PD: This for helps avoiding python bytecode too.
PD2: Nice pictures and links on your webpages Wulfraed. :)
PD3: Just don't imagine a n^16 breaking loop, could that exist?
 
F

Facundo Batista

foo = 0
for item1 in range(10) until foo == 2:
for item2 in range(10) until foo == 2:
foo = item1 + item2
if foo == 2: print "Let's see"
print foo

In this case, I'll use the following:

try:
for item1 in range(10):
for item2 in range(10):
if item1 + item2 == 2:
print "Let's see"
raise StopIteration
except StopIteration:
pass
print item1 + item2

And I tell you what. Actually I'm very lousy remembering things, and
if I want the loop to stop in a different number, I'll have to change
the code in TWO places. In mine, just one (and this in your codes get
worse with more for levels).

Another approach:

def bar():
for item1 in range(10):
for item2 in range(10):
if item1 + item2 == 2:
print "Let's see"
return item1 + item2
foo = bar()
print foo

.. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://pyar.decode.com.ar/
 
R

Ron_Adam

-- Your code
foo = 0
for item1 in range(10):
for item2 in range(10):
foo = item1 + item2
if foo == 2:
print "Let's see"
break # let's go
if (item1 + item2) == 2:
break # one more time
print foo

The outer loop never reaches 1, so we can get rid of it along with the
second if statement, the additions aren't needed either.

So what you have left is this.

for foo in range(3):
pass
print "Let's see"
print foo

Which is the same as:

print "let's see\n", foo


I know that isn't the point. Just couldn't resist. ;)

Ron_Adam
 
B

brainsucker

Well facundo, I knew that you were going for the return inside the
loop.
The exception is cool, but not for newcomers.
My proposend code is simpler clearer and more compact, I keep watching
your code, and don't know....

Funcs for breaking loops, exceptions for breaking loops.
:eek:
 
B

brainsucker

As you know is not functional...
It represents something that happens everyday on Python programming.
We can reduce the other examples of code to:

prinf foo

Too. :)
 
B

brainsucker

Franciso, some more code.

Breaking with two conditions, and fun with exceptions:

moflo = 1
try:
for item1 in range(10):
if (item1 * moflo) == 3: raise StopIteration
for item2 in range(10):
if (item2 * moflo) == 2: raise StopIteration
print "Let's see"
except StopIteration:
pass

As oppossed to:

leave = False
moflo = 1
for item1 in range(10) until ((item1 * moflo) == 3) or leave:
for item2 in range(10) until leave:
if (item2 * moflo) == 2: leave = True
print "Let's see"

What can I say.
 
B

Bengt Richter

Franciso, some more code.

Breaking with two conditions, and fun with exceptions:

moflo = 1
try:
for item1 in range(10):
if (item1 * moflo) == 3: raise StopIteration
for item2 in range(10):
if (item2 * moflo) == 2: raise StopIteration
print "Let's see"
except StopIteration:
pass

As oppossed to:

leave = False
moflo = 1
for item1 in range(10) until ((item1 * moflo) == 3) or leave:
for item2 in range(10) until leave:
if (item2 * moflo) == 2: leave = True
print "Let's see"

What can I say.
You could play with until in this form (in 2.4 generator expressions):
... if not cond: return True
... raise StopIteration
... ...
0 1 2

actually, that until would read better as "notyet" after the "if"

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top