#encoding=utf-8
################### 条件和循环 ######################
#*************** Part 1: if 语句**************************
#多重条件表达式
#单个 if 语句可以通过使用布尔操作符 and , or 和 not 实现多重判断条件或是否定判断条件.
#if 1<10 and 2<10 :
# print('this is test')
#*************** Part 2: else 语句 **************************
#name = input('please input name:')
#if name !='dave':
# print('the name is not Dave')
#else:
# print('the name is dave')
#避免“悬挂 else”
#Python 使用缩进而不是用大括号标记代码块边界的设计, 不仅帮助强化了代码的正确性,
#而且还暗中帮助程序员避免了语法上正确的代码中存在潜在的问题.
#如果if 和else 的个数不匹配,那么在 C 语言中, 规则是 else 与最近的 if 搭配.而Python是由缩进来决定的。
#if 2<5:
# print('2<5')
# if 2<4:
# print('2<4')
# else:
# print('2>4')
#或者:
#if 2<5:
# print('2<5')
# if 2<4:
# print('2<4')
#else:
# print('2>4')
#*************** Part 3 : elif (即 else-if )语句 **************************
#elif 是 Python 的 else-if 语句, 它检查多个表达式是否为真, 并在为真时执行特定代码块中的代码.
#num = input('plseze input a num:')
#if int(num)<100:
# print('num < 100')
#elif int(num) <200:
# print('num<200')
#elif int(num)<300:
# print('num<300')
#else:
# print('num>300')
#*************** Part 4 : 条件表达式(即"三元操作符") **************************
#在Python 2.5 版本里才集成的该语法: X if C else Y .
#在Python 2.5 之前需要使用如下语法来实现:(C and [X] or [Y])[0]
#name = input('plz input a name:')
#name1= 'DBA' if name=='dave' else 'ITer'
#print(name1)
#-->
#plz input a name:bl
#ITer
#*************** Part 5 : while 语句 **************************
#计数循环
#count = 0
#while (count < 4):
# print('the index is: %s' % count)
# count += 1
#-->
#the index is: 0
#the index is: 1
#the index is: 2
#the index is: 3
#无限循环
#while True:
# ....
#*************** Part 6 : for 语句 **************************
#for 语句提供了 Python 中最强大的循环结构.它可以遍历序列成员, 可以用在 列表解析 和 生成器表达式中,
#它会自动地调用迭代器的 next()方法, 捕获 StopIteration 异常并结束循环(所有这一切都是在内部发生的).
############用于序列类型
#for char in 'dave':
# print(char)
#-->
#d
#a
#v
#e
#迭代序列有三种基本方法:
#(1)通过序列项迭代
#nameList = ['Walter', "Nicole", 'Steven', 'Henry']
#for eachName in nameList:
# print(eachName, "Dai")
#-->
#Walter Dai
#Nicole Dai
#Steven Dai
#Henry Dai
#(2)通过序列索引迭代
#nameList = ['Cathy', "Terry", 'Joe', 'Heather','Lucy']
#for nameIndex in range(len(nameList)):
# print(nameList[nameIndex])
#-->
#Cathy
#Terry
#Joe
#Heather
#Lucy
#(3)使用项和索引迭代
#nameList = ['Donn', 'Shirley', 'Ben', 'Janice','David', 'Yen', 'Wendy']
#for i, eachLee in enumerate(nameList):
# print("%d %s" % (i+1, eachLee))
#-->
#1 Donn
#2 Shirley
#3 Ben
#4 Janice
#5 David
#6 Yen
#7 Wendy
###########用于迭代器类型
#用 for 循环访问迭代器和访问序列的方法差不多. 唯一的区别就是 for 语句会为你做一些额外的事情. 迭代器并不代表循环条目的集合.
#迭代器对象有一个 next() 方法, 调用后返回下一个条目. 所有条目迭代完后, 迭代器引发一个 StopIteration 异常告诉程序循环结束.
#for 语句在内部调用 next() 并捕获异常.
#使用迭代器做 for 循环的代码与使用序列条目几乎完全相同.
########### range() 内建函数
#Python 提供了两种不同的方法来调用 range() . 完整语法要求提供两个或三个整数参数:
# range(start, end, step =1)
#range() 会返回一个包含所有 k 的列表, 这里 start <= k < end ,
#从 start 到 end , k 每次递增 step . step 不可以为零,否则将发生错误.
#如果只给定两个参数,而省略 step, step 就使用默认值 1 .
#num=list(range(1,20,5))
#print(num)
#-->
#[1, 6, 11, 16]
#num=list(range(1,5))
#print(num)
#-->
#[1, 2, 3, 4]
#for eachVal in range(2, 19, 3):
# print(eachVal)
#-->
#2
#5
#8
#11
#14
#17
#for eachval in range(1,5):
# print(eachval)
#-->
#1
#2
#3
#4
################ xrange() 内建函数
#xrange() 类似 range() , 不过当你有一个很大的范围列表时, xrange() 可能更为适合, 因为
#它不会在内存里创建列表的完整拷贝. 它只被用在 for 循环中, 在 for 循环外使用它没有意义。
#同样地, 你可以想到, 它的性能远高出 range(), 因为它不生成整个列表。
############### 与序列相关的内建函数
#sorted(), reversed(), enumerate(), zip()
#函数( sorted() 和 zip() )返回一个序列(列表),
#而另外两个函数( reversed() 和 enumerate() )返回迭代器(类似序列)
#albums = ('Poe', 'Gaudi', 'Freud', 'Poe2')
#years = (1976, 1987, 1990, 2003)
#for album in sorted(albums):
# print(album)
#-->
#Freud
#Gaudi
#Poe
#Poe2
#for album in reversed(albums):
# print(album)
#-->
#Poe2
#Freud
#Gaudi
#Poe
#for i, album in enumerate(albums):
# print(i, album)
#-->
#0 Poe
#1 Gaudi
#2 Freud
#3 Poe2
#for album, yr in zip(albums, years):
# print(yr, album)
#-->
#1976 Poe
#1987 Gaudi
#1990 Freud
#2003 Poe2
#*************** Part 7 : break 语句 **************************
#Python 中的 break 语句可以结束当前循环然后跳转到下条语句, 类似 C 中的传统 break .
#常用在当某个外部条件被触发(一般通过 if 语句检查), 需要立即从循环中退出时. break 语句可
#以用在 while 和 for 循环中.
#找出最大的约数:
#num=input('please input a num:')
#count = int(num) / 2
#while count > 0:
# if int(num) % count == 0:
# print(count, 'is the largest factor of', num)
# break
# count -= 1
#-->
#please input a num:10
#5.0 is the largest factor of 10
#*************** Part 8 : continue 语句 ********************
#下面示例显示有次机会来输入密码。
#passwdList=['dave','dba','anqing']
#valid = False
#count = 3
#while count > 0:
# userpwd = input("enter password")
## check for valid passwd
# for eachPasswd in passwdList:
# if userpwd == eachPasswd:
# valid = True
# break
#
# if not valid: # (or valid == 0)
# print("invalid input")
# count -= 1
# continue
# else:
# print('the pwd is right!')
# break
#*************** Part 9 : pass 语句 ********************
#Python 没有使用传统的大括号来标记代码块, 有时,有些地方在语法上要求要有代码, 而Python 中没有对应的空大括号或是分号( ; )
#来表示C 语言中的 "不做任何事" , 如果你在需要子语句块的地方不写任何语句, 解释器会提示你
#语法错误. 因此, Python 提供了 pass 语句, 它不做任何事情 - 即 NOP , ( No OPeration , 无
#操作) 我们从汇编语言中借用这个概念. pass 同样也可作为开发中的小技巧, 标记你后来要完成的代码.
#if True:
# pass
#else:
# pass
#*************** Part 10 : 迭代器和 iter() 函数 ********************
######什么是迭代器?
#迭代器是在版本 2.2 被加入 Python 的, 它为类序列对象提供了一个类序列的接口.
#它们是一组数据结构,你可以利用它们的索引从0 开始一直"迭代" 到序列的最后一个条目.
#用"计数"的方法迭代序列是很简单的. Python 的迭代无缝地支持序列对象, 而且它还允许程序员迭代非序列类型, 包括用户定义的对象.
#迭代器用起来很灵巧, 你可以迭代不是序列但表现出序列行为的对象, 例如字典的 key , 一个文件的行, 等等.
#当你使用循环迭代一个对象条目时, 你几乎不可能分辨出它是迭代器还是序列.
#你不必去关注这些, 因为 Python 让它象一个序列那样操作.
#####为什么要迭代器?
#迭代器的定义:
# 提供了可扩展的迭代器接口.
# 对列表迭代带来了性能上的增强.
# 在字典迭代中性能提升.
# 创建真正的迭代接口, 而不是原来的随机对象访问.
# 与所有已经存在的用户定义的类以及扩展的模拟序列和映射的对象向后兼容
# 迭代非序列集合(例如映射和文件)时, 可以创建更简洁可读的代码.
#####如何迭代?
#根本上说, 迭代器就是有一个 next() 方法的对象, 而不是通过索引来计数. 当你或是一个循
#环机制(例如 for 语句)需要下一个项时, 调用迭代器的 next() 方法就可以获得它. 条目全部取
#出后, 会引发一个 StopIteration 异常, 这并不表示错误发生, 只是告诉外部调用者, 迭代完成.
#迭代器也有一些限制. 例如你不能向后移动, 不能回到开始, 也不能复制一个迭代器.
#如果你要再次(或者是同时)迭代同个对象, 你只能去创建另一个迭代器对象.
#reversed() 内建函数将返回一个反序访问的迭代器. enumerate() 内建函数同样也返回迭代器.另外两个新的内建函数, any() 和 all() ,
######使用迭代器
#===字典===
#字典和文件是另外两个可迭代的 Python 数据类型. 字典的迭代器会遍历它的键(keys)
#legends = { ('Poe', 'author'): (1809, 1849, 1976),
#('Gaudi', 'architect'): (1852, 1906, 1987),
#('Freud', 'psychoanalyst'): (1856, 1939, 1990)
#}
#
#for eachLegend in legends:
# print('Name: %s\tOccupation: %s' % eachLegend)
# print(' Birth: %s\tDeath: %s\tAlbum: %s\n' % legends[eachLegend])
#-->
#Name: Poe Occupation: author
# Birth: 1809 Death: 1849 Album: 1976
#
#Name: Gaudi Occupation: architect
# Birth: 1852 Death: 1906 Album: 1987
#
#Name: Freud Occupation: psychoanalyst
# Birth: 1856 Death: 1939 Album: 1990
#===文件===
#文件对象生成的迭代器会自动调用 readline() 方法. 这样, 循环就可以访问文本文件的所有
#行. 程序员可以使用 更简单的 for eachLine in myFile 替换 for eachLine in myFile.readlines() :
#myFile = open('Dave.txt')
#for eachLine in myFile:
# print(eachLine)
#-->
#Dave is DBA!
#Dave is writing Python!
#Dave come from anqing!
#*************** Part 11 : 列表解析 ********************
#列表解析( List comprehensions, 或缩略为 list comps ) 来自函数式编程语言 Haskell . 它
#是一个非常有用, 简单, 而且灵活的工具, 可以用来动态地创建列表.
#
#列表解析的语法:
#[expr for iter_var in iterable]
#这个语句的核心是 for 循环, 它迭代 iterable 对象的所有条目. 前边的 expr 应用于序列的每个成员, 最后的结果值是该表达式产生的列表.
#print([x ** 2 for x in range(6)])
#-->
#[0, 1, 4, 9, 16, 25]
#
#结合if语句,列表解析还提供了一个扩展版本的语法:
#[expr for iter_var in iterable if cond_expr]
#这个语法在迭代时会过滤/捕获满足条件表达式 cond_expr 的序列成员.
#seq = [11, 10, 9, 9, 10, 10, 9, 8, 23, 9, 7, 18, 12, 11, 12]
#print([x for x in seq if x % 2])
#-->
#[11, 9, 9, 9, 23, 9, 7, 11]
#===矩阵样例===
#print([(x+1,y+1) for x in range(3) for y in range(5)])
#-->
#[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5)]
#*************** Part 12 : 生成器表达式 ********************
#生成器表达式是列表解析的一个扩展.生成器是特定的函数, 允许你返回一个值, 然后"暂停"代码的执行, 稍后恢复.
#
#列表解析的一个不足就是必要生成所有的数据, 用以创建整个列表. 这可能对有大量数据的迭
#代器有负面效应. 生成器表达式通过结合列表解析和生成器解决了这个问题.
#
#生成器表达式在 Python 2.4 被引入, 它与列表解析非常相似,而且它们的基本语法基本相同;
#不过它并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这
#个条目“产生”(yield)出来. 生成器表达式使用了"延迟计算"(lazy evaluation), 所以它在使用内存上更有效.
#列表解析:
# [expr for iter_var in iterable if cond_expr]
#生成器表达式:
# (expr for iter_var in iterable if cond_expr)
#生成器并不会让列表解析废弃, 它只是一个内存使用更友好的结构
#=== 交叉配对例子 ===
#rows = [1, 2, 3]
#def cols(): # example of simple generator
# yield 2
# yield 1
#
##不需要创建新的列表, 直接就可以创建配对. 我们可以使用下面的生成器表达式:
#
#x_product_pairs = ((i, j) for i in rows for j in cols())
#
#for pair in x_product_pairs:
# print(pair)
#-->
#(1, 2)
#(1, 1)
#(2, 2)
#(2, 1)
#(3, 2)
#(3, 1)
#=== 重构样例 ===
#我们通过一个寻找文件最长的行的例子来看看如何改进代码. 在以前, 我们这样读取文件
#f = open('Dave.txt', 'r')
#longest = 0
#allLines = f.readlines()
#f.close()
#
#for line in allLines:
# linelen = len(line.strip())
#
# if linelen > longest:
# longest = linelen
#
#print(longest)
#-->23
#列表解析允许我们稍微简化我们代码, 而且我们可以在得到行的集合前做一定的处理.
#f = open('Dave.txt', 'r')
#longest = 0
#allLines = [x.strip() for x in f.readlines()]
#f.close()
#for line in allLines:
# linelen = len(line)
# if linelen > longest:
# longest = linelen
#print(longest)
#-->23
#用了迭代器, 文件本身就成为了它自己的迭代器, 不需要调用 readlines() 函数.使用 max() 内建函数得到最长的字符串长度:
#f = open('Dave.txt', 'r')
#longest = max(len(x.strip()) for x in f)
#f.close()
#print(longest)
#去掉文件打开模式(默认为读取), 然后让 Python 去处理打开的文件.
#print(max(len(x.strip()) for x in open('Dave.txt')))