我最近开始学习 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循环?
正如您所说,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。
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.
请记住,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...
您将需要为此使用列表推导
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 惯用语......
只是作为替代方案,如何将迭代/增量操作推广到 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
<
>