关闭

Python——while和for循环

标签: Pythonifwhile
6127人阅读 评论(0) 收藏 举报
分类:

while 循环

一般格式:

while <test>:
	<statements1>
else <test>:
	<statements2>
else为可选部分,当控制权离开循环而又没有碰到break语句时会执行。

>>> x = 'spam'
>>> while x :
	print (x,end=' ')
	x = x[1:]

	
spam pam am m 
注意:这里使用end = ' '关键字参数,使所有输出都出现在同一行,之间用空格隔开

------------------------------------------------------------------------------------------------------------------------------------------------
break、continue、pass和循环else

break:跳出最近所在的循环(跳过整个循环语句)
continue:跳到最近所在循环的开头处(来到循环的首行)
pass:什么事也不做,只是空占位语句
循环else块:只有当循环正常离开时才会执行(也就是没有碰到break语句)

------------------------------------------------------------------------------------------------------------------------------------------------

一般循环格式

加入break和continue后,while的一般循环格式变为:

while <test1>:
	<statements1>
	if <test2>:break
	if <test3>:continue
else:
	<statements2>
------------------------------------------------------------------------------------------------------------------------------------------------
pass语句是无运算的占位语句,当语法需要语句并且还没有任何使用的语句可写时,就可以使用它。它通常用于为复合语句编写一个空的主体。例如,如果想写个无限循环,每次迭代什么也不做,就写个pass

>>> while True :pass
因为主体只是空语句,Python陷入了死循环,这个程序并没有什么用处。以后将会看到它更有意义的用处。例如,忽略try语句所捕获的异常,以及定义带属性的空类对象,而该类实现的对象行为就像其他语言的结构和记录。pass有时指的是“以后会填上”,只是暂时用于填充函数主体而已
def func1():
	pass

def func2():
	pass
我们无法保持函数体为空而不产生语法错误,因此,可以使用pass来替代
【另外:在Python3.0以后,程序中可以使用三个点...来代替pass,这样似乎更加简洁明了】

------------------------------------------------------------------------------------------------------------------------------------------------

continue语句会立即跳到循环的顶端,即跳过本次循环,执行下一次循环

break 语句会立即离开循环

>>> while True:
	name = input('Enter name:')
	if name == 'stop':break
	age = input('Enter age:')
	print('Hello',name,'=>',int(age)**2)

	
Enter name:Gavin
Enter age:2
Hello Gavin => 4
Enter name:Spam
Enter age:20
Hello Spam => 400
Enter name:stop
------------------------------------------------------------------------------------------------------------------------------------------------
循环else

和循环else子句结合时,break语句通常可以忽略其他语言中所需要的搜索状态标志位。

例如,下列程序搜索大于1的因子,来决定正整数y是否为质数:

>>> def judge(y):
	x = y//2
	while x >1:
		if y % x ==0:
			print(y,'has factor',x)
			break
		x -= 1
	else:
		print(y,'is prime')

		
>>> judge(8)
8 has factor 4
>>> judge(19)
19 is prime
>>> judge(119)
119 has factor 17
除了设置标志位在循环结束时进行测试外,也可以在找到因子时插入break。这样一来,循环else分句可以视为只有当没有找到因子时才会执行。如果你没有碰到break,该数就是质数。
【注意,当第一次判断while循环条件就不满足时,也就是一次循环也没有进行时,还是会执行else子句的】

=================================================================================

for循环

一般用法:

for <target> in <object>:
	<statements>
else:
	<statements>
当python运行for循环时,会逐个将序列对象中的元素赋值给目标,然后为每个元素执行循环主体。

for循环也可以用break、continue和else子句

完整格式如下:

for <target>  in <object>:
	<statements>
	if <test>:break
	if <test>:continue
else:
	<statements>
------------------------------------------------------------------------------------------------------------------------------------------------
基础应用:

>>> for x in ['spam','eggs','ham']:
	print(x,end=  ' ')

	
spam eggs ham
下面两个例子会计算列表得到所有元素的和与乘积。
>>> s = 0
>>> for x in [1,2,3,4]:
	s += x

	
>>> x  #这里x这个变量依然是有值的
4
>>> s
10
>>> p = 1
>>> for x in [1,2,3,4]:
	p *= x

	
>>> p
24
在以后,还会知道Python有一些工具,可以自动对列表中的元素应用诸如‘+’和'*'类似的运算,但是使用for循环通常也一样简单
------------------------------------------------------------------------------------------------------------------------------------------------
其他数据类型

不止对于列表适用,for循环对任何序列都适用,for循环还可以应用于字符串和元组,这里就不举例了。
实际上,for循环甚至可以应用在一些根本不是序列的对象上,对于文件和字典也有效。
------------------------------------------------------------------------------------------------------------------------------------------------

在for 循环中的元组赋值

>>> T = [(1,2),(3,4),(5,6)]
>>> for (a,b) in T:
	print(a,b)

	
1 2
3 4
5 6
>>> for x in T :
	print(x)

	
(1, 2)
(3, 4)
(5, 6)
注意上述两个例子的区别。第一个例子可以看做元组解包的赋值运算
这种形式通常和我们将要介绍的zip调用一起使用,以实现并行遍历。在Python中,它通常还和SQL数据库一起使用,其中,查询结果表作为这里使用的列表这样的序列的序列而返回——外围的列表就是数据库表,嵌套的元组是表中的行,元组赋值和列对应

for 循环中的元组使得用items方法来遍历字典中的键和值变得很方便,而不必再遍历键并手动索引以获取值:

>>> D = {'a':1,'b':2,'c':3}
>>> for key in D:
	print(key,'=>',D[key])

	
b => 2
c => 3
a => 1
>>> list(D.items())
[('b', 2), ('c', 3), ('a', 1)]
>>> for (key,value) in D.items():
	print(key,'=>',value)

	
b => 2
c => 3
a => 1
注意for循环中的元组赋值并非一种特殊情况,这一点很重要;单词for之后的任何赋值目标在语法上都是有效的。尽管我们总是在for循环中手动地赋值以解包:
>>> for both in T:
	a,b = both
	print(a,b)

	
1 2
3 4
5 6
------------------------------------------------------------------------------------------------------------------------------------------------

Python3.0 在for循环中扩展的序列赋值

实际上,for循环中的循环变量真的可以是任何赋值目标,在这里,也可以使用Python3.0的扩展序列解包赋值语法,来提取序列中的序列的元素和部分。

扩展序列赋值可以参考这里
------------------------------------------------------------------------------------------------------------------------------------------------

嵌套for循环

这段代码会在对象列表中搜索每个键,然后报告其搜索结果:

>>> items = ['aaa',111,(4,5),2.01]
>>> tests = [(4,5),3.14]
>>> for key in tests:
	for item in items:
		if key == item:
			print(key,'was found')
			break
	else:
		print(key,'not found')

		
(4, 5) was found
3.14 not found
=================================================================================
编写循环的技巧

1.内置range函数返回一系列连续增加的整数,可作为for中的索引
2.内置zip函数返回并行元素的元组的列表,可用于在for中内遍历整个序列。
------------------------------------------------------------------------------------------------------------------------------------------------

循环计数器:while和range

range函数是通用的工具,可用在各种环境中,虽然range常用在for循环中来产生索引,但也可以用在任何需要整数列表的地方。在Python3.0中,range是一个迭代器,会根据需要产生元素,因此,我们需要将其包含到一个list调用中以一次性显示其结果:

>>> list(range(5)),list(range(2,5)),list(range(0,10,2))
([0, 1, 2, 3, 4], [2, 3, 4], [0, 2, 4, 6, 8])
一个参数时,range会产生从零算起的整数列表,但其中不包括该参数的值;
如果传进两个参数,第一个视为下边界。
第三个选用参数可以提供步进值,使用时,Python会对每个连续整数加上步进值(步进值默认为1).
range也可以是非正数或非递增的:
>>> list(range(-5,5))
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
>>> list(range(5,-5,-2))
[5, 3, 1, -1, -3]
从内部实现上来看,for循环以这种方式使用时,会自动处理迭代的细节。如果你真的想要明确得掌控索引逻辑,可以用while循环来实现:
>>> s = 'gavin'
>>> i = 0
>>> while i<len(s):
	print(s[i],end = ' ')
	i+=1

g a v i n 
------------------------------------------------------------------------------------------------------------------------------------------------
非完备遍历:range和分片

一般情况下,在对序列进行遍历时,最好使用Python中的简单的for循环,不要使用while,并且不要在for循环中使用range调用,只将其视为最后的手段。

>>> for item in X:print(item)
然而利用range进行索引的用处是,我们可以通过控制range来实现特殊的遍历,例如,在遍历的过程中跳过一些元素
>>> S = 'abcdefghijklmn'
>>> for i in range(0,len(S),2):print(S[i],end = ' ')

a c e g i k m 
在这里,我们通过所产生的range列表,访问了字符串S中每隔一个的元素,要使用每隔两个的元素,可以把range的第三个参数改为3,以此类推。

然而,这可能不是如今Python中最理想情况下实现的技术,如果你真想跳过序列中的元素,可以用前面介绍的扩展的第三个限制值形式的分片表达式,例如,要使用S中每隔一个的字符串,可以用步进值2来分片:
>>> for item in S[::2]:print(item,end=' ')

a c e g i k m
结果是相同的,但对我们来说更容易编写,对其他人来说,更容易阅读。
------------------------------------------------------------------------------------------------------------------------------------------------

修改列表:range

可以使用range和for的组合的常见场合就是在循环中遍历列表时对其进行修改。例如,假设你因某种理由要为列表中的每个元素都加1,你可以通过简单的for循环来做,但结果可能不是你想要的:

>>> L = [1,2,3,4,5]
>>> for x in L:
	x+=1

	
>>> L
[1, 2, 3, 4, 5]
>>> x
6
这样并不行,因为修改的是循环变量x,而不是列表L.
要真的在我们遍历列表时对其修改,我们需要使用索引,让我们可以在遍历时替每个位置赋一个一个已更新的值。range/len组合可以替我们产生所需要的索引。
>>> L = [1,2,3,4,5]
>>> for i in range(len(L)):
	L[i] +=1

	
>>> L
[2, 3, 4, 5, 6]
用while循环也可以做,只是运行比较慢。

[x+1 for x in L]
这种形式的列表解析表达式也能做类似的工作,而且没有对最初的列表进行在原处的修改(我们可以把表达式的新列表对象赋值给L,但是这样不会更新原始列表的其他任何引用值)。因为这是循环的核心概念,我们将在以后对列表解析做一个完整的介绍。
------------------------------------------------------------------------------------------------------------------------------------------------
并行遍历:zip和map

内置zip函数可以让我们使用for循环来并行使用多个序列,在基本运算中,zip会取得一个或多个序列为参数,然后返回元组的列表,将这些序列中的并排的元素配成对

例如,假设我们要使用两个列表:

>>> A = [1,2,3,4]
>>> B = [11,22,33,44]
要合并这些列表中的元素,我们可以使用zip来创建一个元组对的列表(和range一样,zip在Python3.0中也是一个可迭代对象,因此,我们必须将其包含在一个list调用中以便一次性显示所有结果)

>>> C = zip(A,B)
>>> C
<zip object at 0x0405BE18>
>>> list(C)
[(1, 11), (2, 22), (3, 33), (4, 44)]
这样的结果在其他环境下也有用,然而搭配for循环中,它就会支持并行迭代:
>>> for (x,y) in zip(A,B):
	print(x,y,'---',x+y)

	
1 11 --- 12
2 22 --- 24
3 33 --- 36
4 44 --- 48
zip可以接受任何类型的序列(其实就是任何可迭代的对象,包括文件),并且可以有两个以上的参数。例如
>>> T1,T2,T3 = (1,2,3),(4,5,6),(7,8,9)
>>> T2
(4, 5, 6)
>>> list(zip(T1,T2,T3))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
当参数长度不同时,zip会以最短序列的长度为准来截断所得到的元组:
>>> S1 = 'abc'
>>> S2 = 'xyz123'
>>> list(zip(S1,S2))
[('a', 'x'), ('b', 'y'), ('c', 'z')]
------------------------------------------------------------------------------------------------------------------------------------------------
使用zip构造字典

前面介绍过,当键和值的集合必须在运行时计算时,这里所用的zip调用也可用于产生字典,并且非常方便。

假设有下列的键和值的列表:

>>> keys = ['spam','eggs','toast']
>>> vals=[1,2,3]
将这些列表变成字典的一种做法就是将这些字符zip起来,并通过for循环并行步进处理:

>>> list(zip(keys,vals))
[('spam', 1), ('eggs', 2), ('toast', 3)]
>>> D2 = {}
>>> for (key,val) in zip(keys,vals):
	D2[key] = val

	
>>> D2
{'toast': 3, 'spam': 1, 'eggs': 2}
不过,在Python2.2和后续版本中,可以完全跳过for循环,直接把zip过的键/值列表传给内置的dict构造函数:
>>> D3 = dict(zip(keys,vals))
>>> D3
{'toast': 3, 'spam': 1, 'eggs': 2}

------------------------------------------------------------------------------------------------------------------------------------------------

产生偏移和元素:enumerate

之前,我们讨论过通过range来产生字符串中元素的偏移值,而不是那些偏移处的元素,不过,在有些程序中,我们两者都需要:需要的元素以及这个元素的偏移值。

可以按照下面这个简单的例子做:

>>> S = 'spam'
>>> offset = 0
>>> for item in S:
	print(item,'appears at offset',offset)
	offset += 1

	
s appears at offset 0
p appears at offset 1
a appears at offset 2
m appears at offset 3
不过内置函数enumerate可以为我们做这件事情:
>>> S = 'spam'
>>> for (offset,item) in enumerate(S):
	print(item,'appears at offset',offset)

	
s appears at offset 0
p appears at offset 1
a appears at offset 2
m appears at offset 3
可以看到:
>>> enumerate(S)
<enumerate object at 0x03602FA8>
>>> list(enumerate(S))
[(0, 's'), (1, 'p'), (2, 'a'), (3, 'm')]
enumerate函数返回一个生成器对象:这种对象支持接下来要学习的迭代协议。简而言之,这个对象有一个__next__方法,由下一个内置函数调用它,并且在循环中每次迭代的时候它会返回一个(index,value)的元祖。我们可以在for循环中通过元组赋值将元组解包(很像是使用zip)

>>> E = enumerate(S)
>>> E
<enumerate object at 0x03602F80>
>>> next(E)
(0, 's')
>>> next(E)
(1, 'p')
>>> next(E)
(2, 'a')
>>> [c*i for (i,c) in enumerate(S)]
['', 'p', 'aa', 'mmm']
要像enumerate、zip和列表解析那样完全理解迭代的概念,需要继续学习。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:338624次
    • 积分:5307
    • 等级:
    • 排名:第5094名
    • 原创:152篇
    • 转载:39篇
    • 译文:5篇
    • 评论:46条
    GitHub
    博客专栏
    JavaWeb框架

    文章:6篇

    阅读:13795
    XML

    文章:7篇

    阅读:26227
    Servlet

    文章:24篇

    阅读:61012
    Python3

    文章:44篇

    阅读:76261
    最新评论