一、可迭代对象
#1、什么是迭代?:迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来 #2、可迭代的对象:在python中,但凡内置有__iter__方法的对象,都是可迭代的对象 #3、迭代器:迭代取值工具,可迭代的对象执行__iter__方法得到的返回值就是迭代器对象 #4、可迭代的对象:str,list,tuple,dict,set,file 获取可迭代对象的方式:无须获取,python内置str,list,tuple,dict,set,file都是可迭代对象 特点: 内置有__iter__方法的都叫可迭代的对象,执行该方法会拿到一个迭代器对象 #5、迭代器对象:文件对象本身就是迭代器对象 1、获取迭代器对象的方式: 执行可迭代对象的__iter__方法,拿到的返回值就是迭代器对象 2、特点: 内置有__next__方法,执行该方法会拿到迭代器对象中的一个值 内置有__iter__方法,执行该方法会拿到迭代器本身 #6. for循环原理分析: 1、for 循环称之为迭代器循环,in后跟的必须是可迭代的对象 2、for循环会执行in后对象的__iter__方法,拿到迭代器对象 3、然后调用迭代器对象的__next__方法,拿到一个返回值赋值给line,执行一次循环体 4、周而复始,直到取值完毕,for循环会检测到异常自动结束循环
1)迭代器的例子
list1=[1,2,3] iter_list1=list1.__iter__() print(iter_list1.__next__()) print(iter_list1.__next__()) print(iter_list1.__next__())
2)文件也是可迭代对象
l=open('a.txt','r',encoding='utf-8') iter_l=l.__iter__() while True: try: print(iter_l.__next__()) except StopIteration: break
二、生成器或迭代器的使用
生成器: 函数内包含有yield关键字, 再调用函数,就不会执行函数体代码,拿到的返回值就是一个生成器对象 总结yield: 1、为我们提供了一种自定义迭代器的方式, 可以在函数内用yield关键字,调用函数拿到的结果就是一个生成器,生成器就是迭代器 2、yield可以像return一样用于返回值,区别是return只能返回一次值,而yield可返回多次 因为yield可以保存函数执行的状态
1)迭代器的使用
def chicken(): print('=====>first') yield 1 print('=====>sencond') yield 2 print('=====>third') yield 3 obj=chicken() print(obj) # 生成器本质就是迭代器,也就是说生成器的玩法其实就是迭代器的玩法 print(obj.__iter__() is obj) res1=obj.__next__() print(res1) res2=obj.__next__() print(res2) res3=next(obj) # 简写 print(res3)
2)用生成器造成无穷多的数
def my_range(): print('start........') n=0 while True: yield n n+=1 obj=my_range() print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) for i in my_range(): print(i)
3)创造一个自己的range
def my_range(start,stop,step=1): n=start while n < stop: yield n #yield 4 n+=step #5 obj=my_range(3,7,2) #3,5, print(obj.__next__()) print(obj.__next__())
4) yield传值使用
def eat(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list food_list.append(food) print('%s start to eat %s' %(name,food)) dog1=eat('user') #1、必须初始化一次,让函数停在yield的位置 res0=dog1.__next__() print(res0) #2、接下来的事,就是喂狗 #send有两方面的功能 #1、给yield传值 #2、同__next__的功能 res1=dog1.send('泔水') print(res1) res2=dog1.send('骨头') print(res2) res3=dog1.send('shit') print(res3)
三、三元表达式
把一个简单的普通的函数变成了一行代码,即三元表达式
def max2(x,y): if x > y: return x else: return y res=max2(10,11) print(res) x=12 y=11 #三元表达式仅应用于: #1、条件成立返回 一个值 #2、条件不成立返回 一个值 # res=x if x > y else y # print(res) def max2(x,y): return x
四、函数递归
1)设置递归限制次数
#函数递归:函数的递归调用,即在函数调用的过程中,又直接或间接地调用了函数本身 import sys print(sys.getrecursionlimit()) sys.setrecursionlimit(10000) print(sys.getrecursionlimit())
2)函数递归调用的例子
# 直接调用 def foo(): print('from foo') foo() foo() # 间接调用 def bar(): print('from bar') foo() def foo(): print('from foo') bar() foo()
3)递归的概念
# 递归分为两个阶段 #1、回溯: # 注意:一定要在满足某种条件结束回溯,否则的无限递归 #2、递推 # 总结: #1、递归一定要有一个明确地结束条件 #2、没进入下一次递归,问题的规模都应该减少 #3、在python中没有尾递归优化
4)递归小高潮,age(n-1)+2
def age(n): if n == 1: return 18 return age(n-1)+2 #age(4)+2 # 分析 # age1 = 18 # age2 = 20 # age3 = 22 # age4 = 24 # age5 = 26 print(age(5))
5)递归特殊列表打印
items=[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,]]]]]]]]]] def tell(l): for item in l: if type(item) is not list: print(item) else: tell(item) tell(items)
五、匿名函数,lambda
# 有名函数 def foo(x,n): return x ** n # ====》匿名函数 f=lambda x,n:x ** n print(f(2,3)) print(f(2,4))
1)强调注意点
1 匿名的目的就是要没有名字,给匿名函数赋给一个名字是没有意义的。也就是使用一次 2 匿名函数的参数规则、作用域关系与有名函数是一样的 3 匿名函数的函数体通常应该是 一个表达式,该表达式必须要有一个返回值
2)匿名函数的应用
练习一,找出下面工资最高人,提示,max
salaries={ 'zhangsan':3000, 'lisi':1000, 'Mr.C':10000, 'Tina':5000 }
salaries={ 'zhangsan':3000, 'lisi':1000, 'Mr.C':10000, 'Tina':5000 } print(max(salaries,key=lambda x:salaries[x]))
相应的求工资工资最低的那个人
print(min(salaries,key=lambda x:salaries[x]))
按照工资的高低顺序排列
salaries1=sorted(salaries,key=lambda x:salaries[x]) #默认是升序排 salaries2=sorted(salaries,key=lambda x:salaries[x],reverse=True) #降序 print(salaries1) print(salaries2)
练习二,map,映射关系
将列表变成成 [1,4,9,16,25]
nums=[1,2,3,4,5]
nums=[1,2,3,4,5] res=map(lambda x:x**2,nums) print(list(res))
将列表['zhangsan','lisi','Tina']中的所有元素加上"_SB"
names=['zhangsan','lisi','Tina'] res=map(lambda x:x+'_SB',names) print(list(res))
之上升级需求['zhangsan','lisi','Tina','lufei'],除了'lufei'加"_NB"外,其他加"_SB"
names=['zhangsan','lisi','Tina','lufei'] res=map(lambda x:x+'_NB' if x == 'lufei' else x + '_SB',names) print(list(res))
练习三,reduce,合并
求1+2+3+4......99+100的和
from functools import reduce res1=reduce(lambda x,y:x+y,range(1,101),100) # 出始值是100 res2=reduce(lambda x,y:x+y,range(1,101)) # 默认初始值是0 print(res1)
字符串拼接
l=['my','name','is','god'] res=reduce(lambda x,y:x+' '+y,l,'Oh,') print(res)
练习四,过滤 filter
['zhangsan_sb','lisi_nb','Tina_sb','lufei_nb']过滤出后面是sb的人
names=['zhangsan_sb','lisi_sb','Tina_sb','lufei_nb'] # res1=filter(lambda x:True if x.endswith('sb') else False,names) # 画蛇添足 res2=filter(lambda x:x.endswith('sb'),names) print(list(res2))
过滤出工资大于4000的
salaries={ 'zhangsan':3000, 'lisi':1000, 'Mr.C':8000, 'Tina':5000 }
res=filter(lambda k:salaries[k] >= 4000,salaries) print(list(res))
六、生成式与生成器表达式
1)列表生成式
列表生成器基本操作
l=['egg%s' %i for i in range(10)] print(l) ll=('egg%s' %i for i in range(10)) # 节约内存 print(ll) print(list(ll)) nums=[i**2 for i in range(10) if i > 3] print(nums)
将names=['zhangsan','lisi_sb','wudalang','tangsan']中的名字全部变大写
names=['zhangsan','lisi_sb','wudalang','tangsan'] names=[name.upper() for name in names] print(names)
将names=['zhangsan','lisi_sb','wudalang','tangsan']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
names=['zhangsan','lisi_sb','wudalang','tangsan'] l=[len(name) for name in names if not name.endswith('sb')] print(l)
2)字典生成式
d={'user%i'%i:i for i in range(10) if i > 0} print(d) userinfo=[('egon','123'),('alex','456'),('wxx','679')] dic={k:v for k,v in userinfo} print(dic)
3)生成器表达式
g=(i for i in range(10)) print(g) print(next(g)) print(next(g)) print(next(g)) chicken=('egg%s' %i for i in range(3)) # print(chicken) print(next(chicken)) print(next(chicken)) print(next(chicken)) with open('a.txt','r',encoding='utf-8') as f: nums=(len(line) for line in f) # print(nums) # print(nums) # print(next(nums)) print(max(nums))
强调:()和[] 的区别
七、import导入模块
1)如何导入模块
# 导入模块方式一 import spam import spam as sm # 使用方法 spam.read1() # 导入模块方式二 # from spam import money,read1,read2,change # from spam import * # 使用方法 read1()
注意点,对于from spam import *,*指所有,也可对*进行控制
__all__=['money','read1'] # from spam import *,控制的就是*所导入的名字
2)定义模块的调试,避免到导入时执行调试的代码
# 当文件被当做脚本执行时__name__的值为"__main__" # 当文件被导入时__name__的值为"模块名" # print(__name__) # main()可快速写成__name__ == '__main__' if __name__ == '__main__': # 改行代码用于区分python文件的两种不同用途,应该写在文件末尾 read1() read2() change()
3)模块之间嵌套导入
1、尽可能的避免嵌套导入模块 2、导入的模块,放入最后或执行函数导入
4)不在同级目录下的导入
# 方法一,加路径 import sys sys.path.append(r'D:\oldboyedu\manth-02\day-01\dir') print(sys.path) # sys.path是以当前执行文件为准的路径 import spam # 方法二,在同级目录的子集 from dir import spam from dir1.dir2 import spam # 在同级目录的孙集
5)在被导入的模块中再导入别人模块
from . import m2 # 从当前路径寻找其他模块 from .. import m2 # 从上层路径寻找其他模块