For loops (novice)

萝らか妹 提交于 2020-01-11 08:29:11

问题


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

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

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

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


回答1:


As you say, a for loop iterates through the elements of a list. The list can contain anything you like, so you can construct a list beforehand that contains each step.

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

For example:

def doubler(x):
    while True:
        yield x
        x *= 2

for i in doubler(1):
    print i

The above for loop will print

1
2
4
8

and so on, until you press Ctrl+C.




回答2:


You can use a generator expression to do this efficiently and with little excess code:

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

Generator expressions work just like defining a manual generator (as in Greg Hewgill's answer), with a syntax similar to a list comprehension. They are evaluated lazily - meaning that they don't generate a list at the start of the operation, which can cause much better performance on large iterables.

So this generator works by waiting until it is asked for a value, then asking range(10) for a value, doubling that value, and passing it back to the for loop. It does this repeatedly until the range() generator yields no more values.




回答3:


Bear in mind that the 'list' part of the Python can be any iterable sequence.

Examples:

A string:

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

A file:

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

A dictionary:

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

A slice of a list:

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

etc etc etc etc

So it really is a lot deeper than 'just some list'

As others have stated, just set the iterable to be what you want it to be for your example 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...



回答4:


You will want to use list comprehensions 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 list comprehension syntax is a follows:

[EXPRESSION for VARIABLE in ITERABLE if CONDITION]

Under the hood, it acts similar to the map and filter function:

def f(VARIABLE): return EXPRESSION
def c(VARIABLE): return CONDITION

filter(c, map(f, ITERABLE))

Example given:

def square(x): return x**2

print map(square, xrange(10))

and

def hypercube(x): return x**x

print map(hypercube, xrange(10))

Which can be used as alternative approach if you don't like list comprehensions. You could as well use a for loop, but that would step away from being Python idiomatic...




回答5:


Just for an alternative, how about generalizing the iterate/increment operation to a lambda function so 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 isn't that much:

seq 7.98655080795
gen 6.19856786728

[EDIT]

To support reverse iteration and with a 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 chosen by the iterator sign, rather than the difference between start and end values.



来源:https://stackoverflow.com/questions/10440493/for-loops-novice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!