For loops (beginners)

I recently started learning Python, and the concept of loops is still a bit confusing for me. I understand that it usually follows the for x in y format, where y is just a list.

For each loop, for (int n: someArray) becomes for n in someArray ,

And the for for (i = 0; i < 9; i-=2) loop for (i = 0; i < 9; i-=2) can be represented for i in range(0, 9, -2)

Suppose that instead of a constant increment, I wanted i*=2 or even i*=i . Is this possible, or will I have to use a while loop?

+7
python increment loops for-loop
May 03 '12 at 23:00
source share
5 answers

As you say, the for loop iterates through list items. The list may contain everything you like, so you can pre-compile a list containing each step.

Cycle

A for can also iterate over "generator" , which is a small piece of code instead of the actual list. In Python, range() is actually a generator (in Python 2.x, although range() returned a list, and xrange() was a generator).

For example:

 def doubler(x): while True: yield x x *= 2 for i in doubler(1): print i 

The above for loop prints

 1 2 4 8 

etc. until you press Ctrl + C.

+11
May 3 '12 at 23:08
source share
โ€” -

You can use an expression to do this efficiently and with a little redundant code:

 for i in (2**x for x in range(10)): #In Python 2.x, use `xrange()`. ... 

Generator expressions work the same way as defining a manual generator (as in Greg Hewgill answer ), with syntax similar to list comprehension. They are evaluated lazily - this means that they do not generate a list at the beginning of the operation, which can lead to significantly better performance at large iterations.

So this generator works, waiting until it is asked to enter a value, then query range(10) for the value, doubling that value and passing it to the for loop. It does this several times until the range() generator gives more values.

+8
May 03 '12 at 23:15
source share

Remember that part of the โ€œlistโ€ in Python can be any iterative sequence.

Examples:

Line:

 for c in 'abcdefg': # deal with the string on a character by character basis... 

File:

 with open('somefile','r') as f: for line in f: # deal with the file line by line 

Dictionary:

 d={1:'one',2:'two',3:'three'} for key, value in d.items(): # deal with the key:value pairs from a dict 

List Slice:

 l=range(100) for e in l[10:20:2]: # ever other element between 10 and 20 in l 

etc. etc. etc.

So itโ€™s really a lot deeper than โ€œjust some listโ€

As others have stated, simply set the iterable to be what you want it to answer your questions:

  for e in (i*i for i in range(10)): # the squares of the sequence 0-9... l=[1,5,10,15] for i in (i*2 for i in l): # the list l as a sequence * 2... 
+5
May 03 '12 at 23:19
source share

Do you want to use a list of concepts for this

 print [x**2 for x in xrange(10)] # X to the 2nd power. 

and

 print [x**x for x in xrange(10)] # X to the Xth power. 



The syntax for list comprehension is as follows:

 [EXPRESSION for VARIABLE in ITERABLE if CONDITION] 



Under the hood, it acts similarly to the display and filter functions :

 def f(VARIABLE): return EXPRESSION def c(VARIABLE): return CONDITION filter(c, map(f, ITERABLE)) 

Example:

 def square(x): return x**2 print map(square, xrange(10)) 

and

 def hypercube(x): return x**x print map(hypercube, xrange(10)) 

What can be used as an alternative approach if you do not like the lists of lists. You could also use a for loop, but that would fall back on idiomatic Python ...

+1
May 03 '12 at 23:08
source share

Just for an alternative, how about generalizing an iteration / increment operation to a lambda function so that you can do something like this:

 for i in seq(1, 9, lambda x: x*2): print i ... 1 2 4 8 

Where seq is defined below:

 #!/bin/python from timeit import timeit def seq(a, b, f): x = a; while x < b: yield x x = f(x) def testSeq(): l = tuple(seq(1, 100000000, lambda x: x*2)) #print l def testGen(): l = tuple((2**x for x in range(27))) #print l testSeq(); testGen(); print "seq", timeit('testSeq()', 'from __main__ import testSeq', number = 1000000) print "gen", timeit('testGen()', 'from __main__ import testGen', number = 1000000) 

The difference in performance is not much:

 seq 7.98655080795 gen 6.19856786728 

[EDIT]

Support reverse iteration and default argument ...

 def seq(a, b, f = None): x = a; if b > a: if f == None: f = lambda x: x+1 while x < b: yield x x = f(x) else: if f == None: f = lambda x: x-1 while x > b: yield x x = f(x) for i in seq(8, 0, lambda x: x/2): print i 

Note. This behaves differently to range / xrange , in which the direction test < / > is selected by the iterator icon, and not the difference between the start and end values.

0
Nov 25 '13 at 10:01
source share



All Articles