8

我最近开始学习 Python,for 循环的概念对我来说还是有点困惑。我知道它通常遵循格式for x in y,其中y只是一些列表。

for-each 循环for (int n: someArray) 变为for n in someArray,

而for循环for (i = 0; i < 9; i-=2)可以表示为for i in range(0, 9, -2)

假设我想要的不是一个恒定的增量,i*=2甚至是i*=i。这可能吗,还是我必须改用while循环?

4

5 回答 5

12

正如您所说,for循环遍历列表的元素。该列表可以包含您喜欢的任何内容,因此您可以预先构建一个包含每个步骤的列表。

循环也可以for遍历“生成器”,它是一小段代码,而不是实际的列表。在 Python 中,range()它实际上是一个生成器(尽管在 Python 2.x中,在生成器range()时返回了一个列表xrange())。

例如:

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

for i in doubler(1):
    print i

上面的for循环将打印

1
2
4
8

以此类推,直到您按下 Ctrl+C。

于 2012-05-03T23:08:13.237 回答
8

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.

于 2012-05-03T23:15:18.763 回答
5

请记住,Python 的“列表”部分可以是任何可迭代的序列。

例子:

一个字符串:

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

一份文件:

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

一本字典:

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

列表的一部分:

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

等等等等等等

所以它真的比“只是一些列表”要深得多

正如其他人所说,只需将可迭代设置为您想要的示例问题:

 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...
于 2012-05-03T23:19:47.963 回答
1

您将需要为此使用列表推导

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

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

列表理解语法如下:

[EXPRESSION for VARIABLE in ITERABLE if CONDITION]

在底层,它的作用类似于map 和 filter 函数

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

filter(c, map(f, ITERABLE))

给出的例子:

def square(x): return x**2

print map(square, xrange(10))

def hypercube(x): return x**x

print map(hypercube, xrange(10))

如果您不喜欢列表推导,可以将其用作替代方法。您也可以使用 for 循环,但这将远离 Python 惯用语......

于 2012-05-03T23:08:03.820 回答
0

只是作为替代方案,如何将迭代/增量操作推广到 lambda 函数,以便您可以执行以下操作:

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

定义seq如下:

#!/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)

性能差异不大:

seq 7.98655080795
gen 6.19856786728

[编辑]

为了支持反向迭代并使用默认参数...

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

注意:这与迭代器符号选择方向/测试的range行为不同,而不是开始值和结束值之间的差异。xrange<>

于 2013-11-25T10:01:25.280 回答