一、迭代器
1、迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来
l=['a','b','c','d']count=0while count < len(l): print(l[count]) count+=1
对于列表可以依赖索引取到值,但是数据结构没有索引,比如字典,就需要一种不依赖索引的取值方式,这就需要迭代器了
2、课迭代对象:凡是对象下有__iter__方法,该对象就是可迭代对象(如字符串,列表,字典,集合,元组,文件等)
迭代器对象:内置有__iter__方法和__next__,得到的结果就是迭代器对象(如文件)
可迭代对象执行__iter__方法变成迭代器对象,执行__next__取到里面的值,每次取一个值
dic={'name':'wang','sex':'m',"age":18}dic_iter=dic.__iter__()print(dic_iter.__next__()) #打印取到的nameprint(dic_iter.__next__()) #打印取到的sexprint(dic_iter.__next__()) #打印取到的ageprint(dic_iter.__next__()) #值取完了,抛出异常StopIterationwhile True: try: #处理异常的用法 print(next(dic_iter)) except StopIteration: break
我们通过这种方式取到的值,用for循环就可以简单做到,for循环的原理就是把数据变成迭代器对象执行,并加入处理异常
二、三元表达式和列表推导式
1、三元表达式
def my_max(x,y): return x if x > y else y #判断语句在中间,左边写执行语句,右边写else语句print(my_max(1,3))
2、列表推导式
l=['egg%s' %i for i in range(10)] #列表生成egg0到egg9共十个元素print(l)l=['egg%s' %i for i in range(10) if i >=5] #加上if判断,只取egg5到egg9共五个元素print(l)
3、列表推导式的优点
方便,改变了编程习惯,可称之为声明式编程
三、生成器
1、生成器就是迭代器,只要在函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会得到一个结果,该结果就是生成器对象
2、yield与return比较
相同点:都有返回值的功能
不同点:return只能返回一次值,而yield可以返回多次值
3、实现range功能
def my_range(start,stop): while True: if start == stop: raise StopIteration yield start #碰到yield,程序会暂停,执行next会得到返回值1,接着往下执行start变成2,接着循环,最后取到的值就是1和2 start+=1g=my_range(1,3)for i in my_range(1,3): print(i)
4、实现 python3 tail.py -f access.log | grep 'error'功能
import timedef tail(filepath): with open(filepath, 'r') as f: f.seek(0, 2) while True: line = f.readline() if line: #有新的内容,用yield返回,因为yield可以多次返回值 yield line else: time.sleep(0.2)def grep(pattern,lines): for line in lines: #先查看所有的行,然后找出现error模式的行 if pattern in line: print(line,end='')grep('error',tail('access.log'))
四、面向过程的编程
1、编程思想:核心是过程,即解决问题的步骤,先做什么再做什么,是一种机械式的编程思想
2、优缺点
优点:复杂问题流程化,进而简单化
缺点:可扩展性差
五、递归和二分法
1、递归调用:递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身
递归分为两个阶段:递推,回溯
2、递归的使用:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出
补充:在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
def salary(n): if n == 1: return 100 return salary(n-1)+300print(salary(5))
分析:需要salary(5)的值,返回salary(4)+300,接着取salary(4)的值,一直递推,直到遇到结束条件salary(1)返回值为100,然后回溯,得到salary(5)的值1300
3、二分法
将整个列表切分为两份,取中间值和要找的数据作比较,判断在哪一部分,然后再在那一部分切分,再次取值判断,直到最终找到需要的数据
想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
六、匿名函数
1、lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字
2、有名函数与匿名函数的对比
有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
匿名函数:一次性使用,随时随时定义
应用:max,min,sorted,map,reduce,filter
salaries={ 'wang':3000, 'li':100000, 'tom':10000, 'jim':2000,}print(max(salaries)) #取到的结果是wangprint(min(salaries)) #取到的结果是jim可以看到结果不是我们想要的,因为max,min函数只是把字典的key做比较得到的最大值,最小值,而我们要的是后面的工资的最大值和最小值print(max(salaries.values())) #取到的结果是100000print(min(salaries.values())) #取到的结果是2000
3、用zip函数解决(zip函数也叫拉链函数)
a=[1,2,3]b=['q','w','s','e']res=zip(a,b)print(list(res)) #得到的结果是[(1, 'q'), (2, 'w'), (3, 's')],就是把两个列表的元素一一对应,多余的元素不管解决上面的问题:把上面字典的键值对调res=zip(salaries.values(),salaries.keys())print(max(res)) #得到最大工资的键值对组成的元组(100000, 'li')print(max(res)[1]) #得到工资高的人li
4、通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
print(max(salaries,key=lambda k:salaries[k])) #取到的结果是li,是我们需要的值print(min(salaries,key=lambda k:salaries[k])) #取到的结果是jim,是我们需要的值
5、按照薪资高低进行排序sorted
res=sorted(salaries,key=lambda k:salaries[k])print(res) #得到从低到高的顺序['jim', 'wang', 'tom', 'li'] 如果要求反向排序,即实现从高到低排序print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #得到从高到低的顺序['li', 'tom', 'wang', 'jim']
6、map函数,做映射
l=['wang','li']map(lambda x:x+'_man',l) #对列表的每个元素后面添加_man字符串print(list(map(lambda x:x+'_man',l))) #得到结果['wang_man', 'li_man']
7、reduce函数 :实现合并
from functools import reduce #这个函数需要导入模块print(reduce(lambda x,y:x+y,range(1,101))) #1到100的和,结果是5050
8、filter函数,实现过滤
l=['wang_man','li_man','tom']res=filter(lambda name:name.endswith('man'),l) #元素里面以字符串man结尾的print(list(res)) #过滤的结果['wang_man', 'li_man']
七、内置函数,要看到结果用print打印出来即可
1、数学运算
abs(-5) # 取绝对值,也就是5round(2.6) # 四舍五入取整,也就是3.0pow(2, 3) # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5 结果是3divmod(9,2) # 返回除法结果和余数,适用于判断数据需要分多少页max([1,5,2,-2]) # 求最大值min([9,2,1,3]) # 求最小值sum([1,2,3]) # 求和
2、类型转换
ord("A") # "A"字符对应的数值chr(65) # 数值65对应的字符bool(0) # 转换为相应的真假值,在Python中,0相当于False,下列对象都相当于False: [], (), {}, 0, None, 0.0, ''bin(56) # 返回一个字符串,表示56的二进制数hex(56) # 返回一个字符串,表示56的十六进制数oct(56) # 返回一个字符串,表示56的八进制数list((1, 2, 3)) # 转换为列表[1, 2, 3]tuple([2, 3, 4]) # 转换为(2, 3, 4)dict(a=1, b="hello", c=[1, 2, 3]) # 构建字典{'a': 1, 'b': 'hello', 'c': [1, 2, 3]}
3、序列操作
all([True, 1, "hello!"]) # 所有的元素都相当于True值时返回Trueany(["", 0, False, [], None]) # 有任意一个元素相当于True值时返回Truesorted([1, 5, 3]) # 序列进行排序,也就是[1,3,5]reversed([1, 5, 3]) # 序列反转,也就是[3,5,1]
4、其他常见内置函数
type([1,2,3]) #[1,2,3]是list类型len([1,2,3]) #[1,2,3]的长度是3range(1,5,2) #快速生成序列,1到9,步长为2,结果是1和3enumerate函数:l=['a','b']for i in enumerate(l): print(i) #得到结果是(0, 'a') (1, 'b'),这样可以得到元素对应的索引eval函数和exec函数s='1+2+3'print(eval(s)) #eval用来执行表达式,并返回表达式执行的结果,结果是6print(exec(s)) #exec用来执行语句,不会返回任何值print(eval('1+2+x',{'x':3},{'x':30})) #返回33print(exec('1+2+x',{'x':3},{'x':30})) #返回Noneprint(eval('for i in range(10):print(i)')) #语法错误,eval不能执行表达式print(exec('for i in range(10):print(i)')) #执行语句,得到语句的结果