和其他语言类似,python中使用if...elif...else来形成分支,支持三目操作符 ?:,python中没有switch,但是缩进的特性让if...elif...else的结构同样便于阅读
python中除了break,continue这两个一般的循环控制语句之外,还有一个pass,执行空操作。由于python的语法特性,添加pass可以留空某一个域,避免在调试过程中反复报错。
python中的while循环比其他语言增加了一个特性:支持else。在其他语言中,经常会用到判断是否正常结束循环还是中途break非正常结束,python中利用while...else可以简洁明了地解决这个问题:
i = 0
s = 'this is a test string'
while i < len(s):
if s[i] == 'z' :
break
i += 1
else:
print "There is no z in the string"
由于break会跳出整个while,包括else,所以else后面的语句可以在正常结束的情况下被执行。
python中的for循环更像是perl中的foreach,支持迭代器等特性,功能非常强大
for会访问可迭代对象中的每一个元素,并在所有元素都访问完毕之后结束循环,可迭代对象包括序列、字典、集合、迭代器等。
1. 直接循环序列项:这是最直接的循环方式:
alist = [‘A’,’B’,’C’,’D']
foreach value in alist:
print “value=“,value
如果是字典类型,则直接访问返回的是键,而不是值
2. 通过序列索引来访问序列:通过range()函数等,建立序列的索引对应序列,再通过循环访问该索引序列去访问原序列, 如果要提取索引值的话,有些情况下这种方式也是必要的:
alist = [‘A’,’B’,’C’,’D']
foreach index in range(len(alist)):
print “index=%i,value=%s“ % (index,list[index])
range()方法的完整语法是range(start,end,step=1),range(1,10,2)创建一个1到9的奇数序列,省略最后一个参数则步长默认为1,省略两个参数时,range()语法为range(end),默认从0开始,步长为1并且不可改变:
print range(1,10,2)
print range(1,10)
print range(10)
3. 同时访问索引和内容:通过enumerate()函数,构建一个enumerate对象,for每次循环可以从该对象中获取index和内容的对应元组,如果是字典的话,使用enumerate()方法只会提取键和其对应的索引(注意字典键的无序性),想要同时访问字典的键和值,则需要通过字典的iteritems()方法:
adict = {'A':'B','C':'D','EEE':'F'}
for k,v in adict.iteritems():
print k,v
alist = ['A','B','C','D']
for k,v in enumerate(alist):
print k,v
迭代器和序列不同,并非根据索引来计数,迭代器是有一个next()方法的对象,for语句会使用next()方法获取下一项,并且在条目全部取出后,引发StopIteration异常,从而完成迭代。
通过iter方法可以生成一个迭代器,实际上,序列在for循环的过程中,也会被当成迭代器来迭代工作。字典的迭代器只会遍历字典的键,所以当使用for key in adict的时候,循环的是键,字典可以通过dict.iter*来生成键、值、键值对的迭代器。
迭代器是不可变的,所以不能在循环访问迭代器的过程中对相对应的对象进行改变,如果需要进行改变的操作,则需要利用keys()方法等返回一个键的列表,通过循环访问索引或者键的方式,再对对象进行改变。
在for循环的使用中,可以看到通过range()方法可以实现其他语言中for的简单功能,通过列表生成器生成特有的列表,则可以完成其他语言中for的全部功能。
列表解析:
[expr for iter_var in iterable if cond_expr]
生成器表达式:
(expr for iter_var in iterable if cond_expr)
生成器可以得到一个内存更加友好的结果,他并不创建数字列表,而是在每次计算出一个条目后,就讲该条目产生出来,生成器延迟计算的方式使其在内存上更加有效。
通过生成器,可以非常大限度上地简化代码,并且优化内存结构。
如通过[(x,y)for x in range(3) for y in range(3)]可以形成一个3*3的矩阵,而生成器则是不在内存中生成矩阵,而是逐个计算并生成结果。若要统计一个文件中的非空字节数,直接使用列表解析则可能会占用很大的内存,如使用 sum(len(word)) for line in data for word in line.split() 生成器,则可以事先不占用内存,而是逐行访问文件。
利用生成器,可以重构一些比较复杂的代码,如统计一个文件中的最长行的长度:
f = open(‘file’,’r')
allLineLens = [len(x.strip()) for x in f]
f.close()
return max(allLineLens)
在allLineLens中解析了一个列表,会讲整个文件读取到内存中,使用生成器:
return max(len(x.strip())) for x in open(‘file')
可以逐行读取,优化内存的同时,简化代码。
Python在科学计算上大幅被应用,科学家是讨厌循环的思维方式,生成器的方式将数据的结构更加直观地展示出来,更加能符合科学家的思维习惯应该也有很大关系吧。