一、简介
Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性。须重要理解,if、while、for以及与它们相搭配的 else、 elif、break、continue和pass语句。
二、详解
1、if语句
Python中的if子句由三部分组成:关键字本身、用于判断结果真假的条件表达式以及当表达式为真或者非零时执行的代码块。if 语句的语法如下:
if expression:
expr_true_suite
if 语句的expr_true_suite代码块只有在条件表达式的结果的布尔值为真时才执行,否则将继续执行紧跟在该代码块后面的语句。
(1)多重条件表达式
单个if语句可以通过使用布尔操作符and、or和not,实现多重判断条件或是否定判断条件。
(2)单一语句的代码块
如果一个复合语句(例如if子句、while或for循环)的代码块仅仅包含一行代码,那么它可以和前面的语句写在同一行上。如if make_hard_copy: send_data_to_printer(),这样的单行语句是合法的, 尽管它可能方便,但这样会使得代码更难阅读, 所以推荐将这行代码移到下一行并合理地缩进。另外一个原因就是如果你需要添加新的代码, 你还是得把它移到下一行。
2、else语句
Python提供了与if语句搭配使用的else语句,如果if语句的条件表达式的结果布尔值为假,那么程序将执行 else 语句后的代码。其语法如下:
if expression:
expr_true_suite
else:
expr_false_suite
在C语言中,不会在条件语句范围外发现else语句, 但Python不同,可以在while和for循环中使用else语句,在循环中使用时,else子句只在循环完成后执行,也就是说break语句也会跳过else块。
例:显示出10到20中的数字的最大约数
在CODE上查看代码片派生到我的代码片
#!/usr/bin/env python
def showMaxFactor(num):
count = num / 2
while count > 1:
if (num % count == 0):
print 'largest factor of %d is %d' % (num, count)
break
count = count - 1
else:
print eachNum, 'is prime'
for eachNum in range(10, 21):
showMaxFactor(eachNum)
在CODE上查看代码片派生到我的代码片
largest factor of 10 is 5
11 is prime
largest factor of 12 is 6
13 is prime
largest factor of 14 is 7
largest factor of 15 is 5
largest factor of 16 is 8
17 is prime
largest factor of 18 is 9
19 is prime
largest factor of 20 is 10
3、elif (即else-if )语句
elif是Python的else-if 语句,它检查多个表达式是否为真,并在为真时执行特定代码块中的代码。和else一样,elif 声明是可选的,然而不同的是if 语句后最多只能有一个else语句,但可以有任意数量的 elif 语句。
if expression1:
expr1_true_suite
elif expression2:
expr2_true_suite
...
elif expressionN:
exprN_true_suite
else:
none_of_the_above_suite
在将来的某天,Python可能会支持 switch /case语句,但是完全可以用其他的Python结构来模拟它。在Python中,大量的if-elif 语句并不难阅读。
在CODE上查看代码片派生到我的代码片
if user.cmd == 'create':
action = "create item"
elif user.cmd == 'delete':
action = 'delete item'
elif user.cmd == 'update':
action = 'update item'
else:
action = 'invalid choice... try again!'
上面的语句还可以用序列和成员关系操作符来简化它:
在CODE上查看代码片派生到我的代码片
if user.cmd in ('create', 'delete', 'update'):
action = '%s item' % user.cmd
else:
action = 'invalid choice... try again!'
还可以用Python字典给出更加优雅的解决方案,使用映射对象(比如字典)的一个最大好处就是它的搜索操作比类似语句或是 for 循环这样的序列查询要快很多。
在CODE上查看代码片派生到我的代码片
msgs = {'create': 'create item',
'delete': 'delete item',
'update': 'update item'
}
default = 'invalid choice... try again!'
action = msgs.get(user.cmd, default)
4、条件表达式(即"三元操作符")
三元运算符语法为:X if C else Y,只需要一行完成条件判断和赋值操作:
在CODE上查看代码片派生到我的代码片
>>> x, y = 4, 3
>>> smaller = x if x < y else y
>>> smaller
3
5、while语句
while是一个条件循环语句,与if声明相比,如果 if 后的条件为真,就会执行一次相应的代码块。而while中的代码块会一直循环执行,直到循环条件不再为真。
(1)一般语法
while循环的语法如下:
while expression:
suite_to_repeat
while循环的suite_to_repeat子句会一直循环执行,直到expression值为布尔假。
(2)计数循环
count = 0
while (count < 9):
print 'the index is:', count
count += 1
代码块里包含了print和自增语句,它们被重复执行,直到count不再小于9。索引count在每次迭代时被打印出来然后自增 1。
(3)无限循环
while True:
handle, indata = wait_for_client_connect()
outdata = process_request(indata)
ack_result_to_client(handle, outdata)
"无限"循环永远不会结束,但它不一定是坏事,许多通讯服务器的客户端/服务器系统就是通过它来工作的。
6、for语句
Python提供了的另一个循环机制就是for语句,它是Python中最强大的循环结构。它可以遍历序列成员,可以用在列表解析和生成器表达式中,它会自动地调用迭代器的next()方法,捕获StopIteration异常并结束循环(所有这一切都是在内部发生的)。 Python的for更像是shell或是脚本语言中的foreach循环。
(1)一般语法
for循环会访问一个可迭代对象(例如序列或是迭代器)中的所有元素,,并在所有条目都处理过后结束循环。它的语法如下:
for iter_var in iterable:
suite_to_repeat
每次循环, iter_var迭代变量被设置为可迭代对象(序列、迭代器或者是其他支持迭代的对象)的当前元素,提供给suite_to_repeat 语句块使用。
(2)用于序列类型
for循环可以迭代不同的序列对象,像字符串、 列表、以及元组。
迭代序列有三种基本方法:
通过序列项迭代
在CODE上查看代码片派生到我的代码片
>>> nameList = ['Walter', "Nicole", 'Steven', 'Henry']
>>> for eachName in nameList:
... print eachName, "Lim"
...
Walter Lim
Nicole Lim
Steven Lim
Henry Lim
迭代一个列表.。每次迭代,eacgName变量都被设置为列表中特定某个元素。
通过序列索引迭代
在CODE上查看代码片派生到我的代码片
>>> nameList = ['Cathy', "Terry", 'Joe', 'Heather','Lucy']
>>> for nameIndex in range(len(nameList)):
... print "Liu,", nameList[nameIndex]
...
Liu, Cathy
Liu, Terry
Liu, Joe
Liu, Heather
Liu, Lucy
没有迭代元素, 而是通过列表的索引迭代。但通过直接迭代序列要比索引迭代快。
使用项和索引迭代
在CODE上查看代码片派生到我的代码片
>>> nameList = ['Donn', 'Shirley', 'Ben', 'Janice','David', 'Yen', 'Wendy']
>>> for i, eachLee in enumerate(nameList):
... print "%d %s Lee" % (i+1, eachLee)
...
1 Donn Lee
2 Shirley Lee
3 Ben Lee
4 Janice Lee
5 David Lee
6 Yen Lee
7 Wendy Lee
(3)用于迭代器类型
用for循环访问迭代器和访问序列的方法差不多,迭代器并不代表循环条目的集合,迭代器对象有一个next()方法, 调用后返回下一个条目。 所有条目迭代完后, 迭代器引发一个StopIteration异常告诉程序循环结束,for语句在内部调用next()并捕获异常。
使用迭代器做 for 循环的代码与使用序列条目几乎完全相同。事实上在大多情况下,无法分辨出迭代的是一个序列还是迭代器,因此遍历一个迭代器时,实际上可能指的是要遍历一个序列、迭代器或是一个支持迭代的对象(它有 next()方法)。
(4)range()内建函数
内建函数range()可以把类似foreach的for循环变成你更加熟悉的语句。
Python提供了两种不同的方法来调用range() ,完整语法要求提供两个或三个整数参数:range(start, end, step =1),range()会返回一个包含所有k的列表,其中start <= k < end,从start到end ,k每次递增 ste,step不可以为零,否则将发生错误。
在CODE上查看代码片派生到我的代码片
>>> range(3, 7)
[3, 4, 5, 6]
>>> for eachVal in range(2, 19, 3):
... print "value is:", eachVal
...
value is: 2
value is: 5
value is: 8
value is: 11
value is: 14
value is: 17
range() 还有两种简略的语法格式:range(end)和range(start, end)。 start 默认为0, step默认为1。
(5)xrange()内建函数
xrange()类似range(),不过当有一个很大的范围列表时,xrange() 可能更为适合, 因为它不会在内存里创建列表的完整拷贝。 它只被用在 for 循环中,在 for 循环外使用它没有意义。它的性能远高出 range(),因为它不生成整个列表。在Python的将来版本中,range()可能会像xrange()一样,返回一个可迭代对象(不是列表也不是一个迭代器)。
(6)与序列相关的内建函数
序列相关函数:sorted()、 reversed()、enumerate()和zip(),称为"序列相关"是因为其中两个函数(sorted() 和 zip())返回一个序列(列表),而另外两个函数(reversed() 和 enumerate())返回迭代器(类似序列)。
7、break和continue语句
Python中的break语句可以结束当前循环然后跳转到下条语句,类似C中的break。常用在当某个外部条件被触发(一般通过 if 语句检查),需要立即从循环中退出时.。break 语句可以用在 while 和 for 循环中。
Python里的continue语句和其他高级语言中的传统continue并没有什么不同,它可以被用在while和for循环里。 while循环是条件
性的,而 for 循环是迭代的,所以continue在开始下一次循环前要满足一些先决条件,否则循环会正常结束。
程序中当遇到 continue 语句时, 程序会终止当前循环,并忽略剩余的语句,然后回到循环的顶端。在开始下一次迭代前,如果是条件循环,我们将验证条件表达式。如果是迭代循环,将验证是否还有元素可以迭代。只有在验证成功的情况下,才会开始下一次迭代。
在CODE上查看代码片派生到我的代码片
#!/usr/bin/env python
valid = False
count = 3
passwdList=('abc',)
while count > 0 and valid == False:
input = raw_input("enter password:").strip()
# check for valid passwd
for eachPasswd in passwdList:
if input == eachPasswd:
valid = True
break
if not valid: # (or valid == 0)
print "invalid input"
count -= 1
continue
else:
break
结合使用了while、for、if、break以及continue,来验证用户输入。用户有三次机会来输入正确的密码,阻止用户猜测密码。
8、pass语句
Python中没有对应的空大括号或是分号( ; )来表示如C语言中的"不做任何事",如果需要子语句块的地方不写任何语句, 解释器会提示语法错误。因此,Python 提供了pass语句,它不做任何事情,即NOP(No OPeration),pass同样也可作为开发中的小技巧,标记以后将要完成的代码。
def foo_func():
pass
这样的代码结构在开发和调试时很有用,因为编写代码的时候可能要先把结构定下来,但又不希望它干扰其他已经完成的代码, 在不需要它做任何事情地方放一个pass,将是一个很好的主意。另外它在异常处理中也被经常用到,比如你跟踪到了一个非致命的错误而不想采取任何措施。
9、迭代器和iter()函数
(1)什么是迭代器
迭代器为类序列对象提供了一个类序列的接口,可以利用它们的索引从0开始一直"迭代" 到序列的最后一个条目,用"计数"的方法迭代序列是很简单的。 Python的迭代无缝地支持序列对象,而且它还允许程序员迭代非序列类型, 包括用户定义的对象。
迭代器用起来很灵巧,可以迭代不是序列但表现出序列行为的对象,例如字典的 key 、一个文件的行等等。当使用循环迭代一个对象条目时,不必去关注它是迭代器还是序列。
(2)为什么要迭代器
迭代器的定义:提供了可扩展的迭代器接口、对列表迭代带来了性能上的增强、在字典迭代中性能提升、创建真正的迭代接口,而不是原来的随机对象访问、与所有已经存在的用户定义的类以及扩展的模拟序列和映射的对象向后兼容、迭代非序列集合(例如映射和文件)时, 可以创建更简洁可读的代码。
(3)如何迭代
迭代器有一个next()方法的对象,而不是通过索引来计数。当一个循环机制(例如 for 语句)需要下一个项时,调用迭代器的next()方法就可以获得它。条目全部取出后,会引发一个StopIteration异常,这并不表示错误发生,只是告诉外部调用者迭代完成。
不过,迭代器也有一些限制。 例如不能向后移动,不能回到开始,也不能复制一个迭代器。如果要再次(或者是同时)迭代同个对象,你只能去创建另一个迭代器对象。不过,还有其他的工具来帮助你使用迭代器。
reversed()内建函数将返回一个反序访问的迭代器。enumerate()内建函数同样也返回迭代器。另外两个新的内建函数:any()和 all(),如果迭代器中某个/所有条目的值都为布尔真时,则它们返回值为真。
(4)使用迭代器
序列
在CODE上查看代码片派生到我的代码片
>>> myTuple = (123, 'xyz', 45.67)
>>> i = iter(myTuple)
>>> i.next()
123
>>> i.next()
'xyz'
>>> i.next()
45.670000000000002
>>> i.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
在for循环中for i in seq:do_something_to(i),它会自动调用迭代器的next()方法,并且监视StopIteration异常。
字典
字典和文件是另外两个可迭代的Python数据类型。字典的迭代器会遍历它的键(keys),语句for eachKey in myDict.keys()可以缩写为for eachKey in myDict。
Python还引进了三个新的内建字典方法来定义迭代: myDict.iterkeys() (通过 keys 迭代), myDict.itervalues() (通过 values 迭代)以及myDicit.iteritems() (通过key/value 对来迭代 )。 注意 : in操作符也可以用于检查字典的key是否存在,布尔表达式myDict.has_key(anyKey)可以被简写为anyKey in myDict。
文件
文件对象生成的迭代器会自动调用readline()方法。这样,循环就可以访问文本文件的所有行。可以使用更简单的for eachLine in myFile替 换for eachLine in myFile.readlines()。
(5)可变对象和迭代器
在迭代可变对象的时候修改它们并不是个好主意,这在迭代器出现之前就是一个问题。一个序列的迭代器只是记录当前到达第几个元素,所以若在迭代时改变了元素,更新会立即反映到你所迭代的条目上。在迭代字典的key时,绝对不能改变这个字典。 使用字典的keys()方法是可以的,因为keys() 返回一个独立于字典的列表, 而迭代器是与实际对象绑定在一起的,它将不会继续执行下去。
(6)如何创建迭代器
对一个对象调用iter()就可以得到它的迭代器,它的语法如下:iter(obj)或iter(func, sentinel )。如果传递一个参数给iter(),它会检查你传递的是不是一个序列,如果是则会根据索引从0一直迭代到序列结束。另一个创建迭代器的方法是使用类,一个实现iter()和next()方法的类可以作为迭代器使用。如果是传递两个参数给iter(), 它会重复地调用func,直到迭代器的下个值等于sentinel。
10、列表解析
列表解析( List comprehensions或缩略为list comps ) 来自函数式编程语言Haskell。它是一个非常有用、简单、而且灵活的工具, 可以用来动态地创建列表。
Python支持的函数式编程特性,例如lambda 、map() 以及filter()等,通过列表解析它们可以被简化为一个列表解析式子。map()对所有的列表成员应用一个操作,filter()基于一个条件表达式过滤列表成员,lambda()允许快速地创建只有一行的函数对象。
列表解析的语法:[expr for iter_var in iterable], 它迭代iterable对象的所有条目。其中的expr应用于序列的每个成员,最后的结果值是该表达式产生的列表,迭代变量并不需要是表达式的一部分。
在CODE上查看代码片派生到我的代码片
>>> [x ** 2 for x in range(6)]
[0, 1, 4, 9, 16, 25]
列表解析的表达式可以取代内建的map()函数以及lambda ,而且效率更高。结合 if语句,列表解析还提供了一个扩展版本的语法:[expr for iter_var in iterable if cond_expr],它在迭代时会过滤/捕获满足条件表达式cond_expr的序列成员。
挑选出序列中的奇数:
在CODE上查看代码片派生到我的代码片
>>> seq = [11, 10, 9, 9, 10, 10, 9, 8, 23, 9, 7, 18, 12, 11, 12]
>>> filter(lambda x: x % 2, seq)
[11, 9, 9, 9, 23, 9, 7, 11]
>>> [x for x in seq if x % 2]
[11, 9, 9, 9, 23, 9, 7, 11]
即使不用filter()和lambda,可以使用列表解析来完成操作,获得想要的数字。
矩阵样例:迭代一个有三行五列的矩阵,[(x+1,y+1) for x in range(3) for y in range(5)]。
磁盘文件样例:若有一个数据文件text.txt,需要计算出所有非空白字符的数目,可以把每行分割( split )为单词,,然后计算单词个数:>>> f = open('hhga.txt', 'r');len([word for line in f for word in line.split()])。快速地计算文件大小:>>>import os;os.stat('text.txt').st_size。把每个单词的长度加起来:>>>f.seek(0);sum([len(word) for line in f for word in line.split()])。
11、生成器表达式
生成器表达式是列表解析的一个扩展,只用一行代码就可以创建包含特定内容的列表。另一个重要特性是生成器,生成器是特定的函数,允许返回一个值,然后"暂停"代码的执行,稍后恢复。
列表解析的一个不足就是必要生成所有的数据,用以创建整个列表。这可能对有大量数据的迭代器有负面效应, 生成器表达式通过结合列表解析和生成器解决了这个问题。
生成器表达式与列表解析非常相似,而且它们的基本语法基本相同。不过它并不真正创建数字列表而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目"产生"(yield)出来。生成器表达式使用了"延迟计算"(lazy evaluation),所以它在使用内存上更有效。生成器并不会让列表解析废弃,它只是一个内存使用更友好的结构,基于此,有很多使用生成器地方。
列表解析语法:
[expr for iter_var in iterable if cond_expr]
生成器表达式语法:
(expr for iter_var in iterable if cond_expr)
磁盘文件样例:上述计算文本文件中非空白字符总和,如果这个文件的大小变得很大, 那么这行代码的内存性能会很低,因为要创建一个很长的列表用于存放单词的长度。为了避免创建庞大的列表,使用生成器表达式来完成求和操作,优化后的代码:>>> sum(len(word) for line in data for word in line.split()),是把方括号删除,少了两字节, 而且更节省内存。
交叉配对例子:成器表达式就好像是懒惰的列表解析(这反而成了它主要的优势),它还可以用来处理其他列表或生成器,如:x_product_pairs = ((i, j) for i in rows for j in cols())。
重构样例,寻找文件最长的行的例子:
以前的方法:
在CODE上查看代码片派生到我的代码片
#!/usr/bin/env python
def fun():
f = open('/etc/motd', 'r')
longest = 0
allLines = [x.strip() for x in f.readlines()] #or allLineLens = [len(x.strip()) for x in f]
f.close()
for line in allLines:
linelen = len(line)
if linelen > longest: #or longest = max(allLineLens)
longest = linelen
return longest
新的方法:
使用生成器表达式替换列表解析和max()函数,并去掉文件打开模式(默认为读取):return max(len(x.strip()) for x in open('/etc/motd'))。
三、总结
(1)itertools模块被加入,更加支持了迭代器的应用,列表解析和生成表达式的内容可结合实例分析。
(2)若有不足,请留言,在此先感谢!
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。