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():
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这个变量依然是有值的
>>> p = 1
>>> for x in [1,2,3,4]:
	p *= x
24
在以后,还会知道Python有一些工具,可以自动对列表中的元素应用诸如‘+’和'*'类似的运算,但是使用for循环通常也一样简单 ------------------------------------------------------------------------------------------------------------------ ------------------------------ 其他数据类型

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

在for 循环中的元组赋值

>>> T = [(1,2),(3,4),(5,6)]
>>> for (a,b) in T:
	print(a,b)
>>> 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)
------------------------------------------------------------------------------------------------------------------ 
------------------------------ 

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 = ' ')
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:
[1, 2, 3, 4, 5]
6
这样并不行,因为修改的是循环变量x,而不是列表L.
要真的在我们遍历列表时对其修改,我们需要使用索引,让我们可以在遍历时替每个位置赋一个一个已更新的值。range/len组合可以替我们产生所需要的索引。
>>> L = [1,2,3,4,5]
>>> for i in range(len(L)):
	L[i] +=1
[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)
<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)
(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
{'toast': 3, 'spam': 1, 'eggs': 2}
不过,在Python2.2和后续版本中,可以完全跳过for循环,直接把zip过的键/值列表传给内置的dict构造函数:
>>> D3 = dict(zip(keys,vals))
{'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)
<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和列表解析那样完全理解迭代的概念,需要继续学习。 本文介绍了while和for循环,介绍了循环语句中break、continue、pass和循环else语句的用法,重点介绍了for循环的细节,包括在循环中进行元祖赋值、扩展解包赋值。最后介绍了几种常用的工具:range、zip、map和enumerate
Python 中的循环语句有 2 种,分别是 while 循环和 for 循环,for 循环它常用于遍历字符串、列表、元组、字典、集合等序列类型,逐个获取序列中的各个元素。 for 循环的语法格式如下: 格式中,迭代变量用于存放从序列类型变量中读取出来的元素,所以一般不会在循环中对迭代变量手动赋值;代码块指的是具有相同缩进格式的多行代码(和 while 一样),由于和循环结构联用,因此代码块又称为...
在本篇博客中,我们将讨论 Python 中 for 循环的原理。 我们将从一组基本例子和它的语法开始,还将讨论与 for 循环关联的 else 代码块的用处。 然后我们将介绍迭代对象、迭代器和迭代器协议,还会学习如何创建自己的迭代对象和迭代器。 之后,我们将讨论如何使用迭代对象和迭代器实现 for 循环,以及利用 while 循环通过迭代器协议实现 for 循环逻辑。 最后,我们将反编译一个简单的 for 循环,并逐步介绍 Python 解释器在执行 for 循环时执行的指令,以满足大家的好奇心。这些有助于