Python之生成器及内置函数篇4

时间:2021-06-24 14:31:49

一、可迭代对象

#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=[,,]
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
print('=====>sencond')
yield
print('=====>third')
yield 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=
while True:
yield n
n+= 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=):
n=start
while n < stop:
yield n #yield
n+=step # obj=my_range(,,) #,,
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')
#、必须初始化一次,让函数停在yield的位置
res0=dog1.__next__()
print(res0) #、接下来的事,就是喂狗
#send有两方面的功能
#、给yield传值
#、同__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(,)
print(res)
x=
y= #三元表达式仅应用于:
#、条件成立返回 一个值
#、条件不成立返回 一个值
# res=x if x > y else y
# print(res)
def max2(x,y):
return x

四、函数递归

1)设置递归限制次数

#函数递归:函数的递归调用,即在函数调用的过程中,又直接或间接地调用了函数本身
import sys
print(sys.getrecursionlimit())
sys.setrecursionlimit()
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)递归的概念

# 递归分为两个阶段
#、回溯:
# 注意:一定要在满足某种条件结束回溯,否则的无限递归
#、递推 # 总结:
#、递归一定要有一个明确地结束条件
#、没进入下一次递归,问题的规模都应该减少
#、在python中没有尾递归优化

4)递归小高潮,age(n-1)+2

def age(n):
if n == :
return
return age(n-)+ #age()+
# 分析
# age1 =
# age2 =
# age3 =
# age4 =
# age5 =
print(age())

5)递归特殊列表打印

items=[,[,[,[,[,[,[,[,[,[,]]]]]]]]]]
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':,
'lisi':,
'Mr.C':,
'Tina':
}
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=[,,,,]
res=map(lambda x:x**,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(,),) # 出始值是100
res2=reduce(lambda x,y:x+y,range(,)) # 默认初始值是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] >= ,salaries)
print(list(res))

六、生成式与生成器表达式

1)列表生成式

列表生成器基本操作
l=['egg%s' %i for i in range()]
print(l) ll=('egg%s' %i for i in range()) # 节约内存
print(ll)
print(list(ll)) nums=[i** for i in range() if i > ]
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() if i > }
print(d) userinfo=[('egon',''),('alex',''),('wxx','')]
dic={k:v for k,v in userinfo}
print(dic)

3)生成器表达式

g=(i for i in range())
print(g)
print(next(g))
print(next(g))
print(next(g)) chicken=('egg%s' %i for i in range())
# 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)模块之间嵌套导入

、尽可能的避免嵌套导入模块
、导入的模块,放入最后或执行函数导入

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 # 从上层路径寻找其他模块