day13叠加多个装饰器,迭代器,生成器,三元表达式、列表生成式、字典生成式、生成器表达式
上节课复习:
闭包函数的实际应用就是装饰器,装饰器分为:
1. 无参装饰器
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
2. 有参装饰器
def outter2(x,y,z):
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter
3. 语法糖:在被装饰对象正上方单独一行写
无参:@装饰器的名字
有参:@装饰器的名字(arg1,arg2,...) #义括号内参数1,参数2...
@timmer # index=timmer(index)
def index():
pass
@auth2(engine='file') # @名字 # index=名字(index)
def index():
pass
今日内容:
0. 叠加多个装饰器:加载顺序与执行顺序是什么?
例如:
@装饰器1
@装饰器2 ???
@装饰器3 #f1=装饰器3(f1)
def f1():
pass
f1()
1. 迭代器(***)
2. 自定义迭代器的方式:生成器(***)
3. 三元表达式\列表生成式\生成器表达式\字典生成式(*****)
4. 函数的递归调用与二分法
5. 面向过程编程(*****)
补充:
1. 匿名函数(一次性的工具)+max,min,sorted,filter,reduce,map(*****)
2. 内置函数
1.加载装饰器总结:
# 加载装饰器是什么?就是将原函数名偷梁换柱成了装饰器最内层那个wrapper函数;
# 在加载完毕后,调用原函数其实就是在调用装饰器最内层wrapper函数。
2.# 当一个被装饰的对象同时叠加多个装饰器时,
# 装饰器的加载顺序是:自下而上。()己理解为:一行行代码从上而下运行阶段,装饰器语法糖的加载顺序:自下而上,所以2个阶段加载阶段先工作起来。
# 装饰器内wrapper函数的执行顺序是:自上而下。()己理解为:遇到原始函数调用阶段,装饰器语法糖的执行顺序:自上而下。
# import time
#
# def timmer(func): #func=wrapper2的内存地址
# def wrapper1(*args, **kwargs):
# print('===================================>wrapper1运行了')
# start=time.time()
# res = func(*args, **kwargs) #===========================>跳到wrapper2去执行了,
# stop=time.time()
# print('run time is %s' %(stop - start))
# return res
# return wrapper1
#
# def auth(engine='file'):
# def xxx(func): # func=最原始那个index的内存地址
# def wrapper2(*args, **kwargs):
# print('===================================>wrapper2运行了')
# name=input('username>>>: ').strip()
# pwd=input('password>>>: ').strip()
# if engine == 'file':
# print('基于文件的认证')
# if name == 'egon' and pwd == '123':
# print('login successfull')
# res = func(*args, **kwargs)
# return res
# elif engine == 'mysql':
# print('基于mysql的认证')
# elif engine == 'ldap':
# print('基于ldap的认证')
# else:
# print('错误的认证源')
# return wrapper2
# return xxx
#
# @timmer # index=timmer(wrapper2的内存地址) #index=wrapper1的内存地址
# @auth(engine='file') #加载顺序:先下后上,@auth为下,@timmer为上。@xxx #index=xxx(最原始那个index的内存地址) #index=wrapper2的内存地址
# def index():
# print('welcome to index page')
# time.sleep(2)
#
# index() #wrapper1的内存地址()
一个函数上有多个装饰器运行原理总结:
程序运行时从上到下运行代码,碰到装饰器从下往上进行装饰器加载。
@装饰器1 #加载时装饰器语法糖的实质是f1=装饰器1(f1)
@装饰器2 #f1=装饰器2(f1)
@装饰器3 #f1=装饰器3(f1)
def f1():
pass
f1()调用f1函数触发装饰器执行,即加载后实质对应的函数从上往下执行。
所以装饰器执行时,实质为最上面的装饰器对下一行装饰器包了一个功能,中间的给下一行装饰器包了一个功能,最下面装饰器是给原始函数包一个功能,像包洋葱一样。通过第一句话实现给原始函数添加很多功能。
import time def timmer(func): #func=原始函数index的内存地址。 def wrapper1(*args, **kwargs): print('===================================>wrapper1运行了') start=time.time() res = func(*args, **kwargs) #===========================>跳到wrapper2去执行了, stop=time.time() print('run time is %s' %(stop - start)) return res return wrapper1 def auth(engine='file'): def xxx(func): # func=wrapper1的内存地址。 def wrapper2(*args, **kwargs): print('===================================>wrapper2运行了') name=input('username>>>: ').strip() pwd=input('password>>>: ').strip() if engine == 'file': print('基于文件的认证') if name == 'egon' and pwd == '123': print('login successfull') res = func(*args, **kwargs) return res elif engine == 'mysql': print('基于mysql的认证') elif engine == 'ldap': print('基于ldap的认证') else: print('错误的认证源') return wrapper2 return xxx @auth(engine='file') @timmer def index(): print('welcome to index page') time.sleep(2) index() #wrapper2的内存地址()
迭代器
1. 什么是迭代器?
器》》工具。
那么什么是迭代?
迭代指的是一个重复的过程,每一次重复的结果都是基于上一次的结果而来的。
li=['a','b','c','d','e']
li=('a','b','c','d','e')
li='hello'
i=0
while i < len(li):
print(li[i])
i+=1
迭代器指的是迭代取值的工具,该工具的特点是可以不依赖于索引取值。
2. 为何要用迭代器?
对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。
但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器。
为了找出一种通用的并且可以不依赖于索引的迭代取值方式。
3. 如何用迭代器?
可迭代的对象:但凡内置有.__iter__方法的对象都称之为可迭代的对象。
迭代器对象:既内置有__iter__方法,又内置有__next__方法的对象。
总结:迭代器对象一定是可迭代对象,但可迭代对象不一定是迭代器对象。
内置__iter__方法是为了用,怎么用? 关于__iter__方法:
调用可迭代对象的__iter__会得到一个迭代器对象。
调用迭代器对象的__iter__会得到迭代器本身。
4. 总结迭代器的优缺点:
优点:
1. 提供了一种通用的并且可以不依赖于索引的迭代取值方式。
2. 同一时刻在内存中只有一个值,更加节省内存。
eg:定义一个列表,列表会申请内存空间存列表内所有的值,当值比较多时会很占内存。
而创造一个迭代器对象时,不会把值放到内存,只是在取值时同一时刻内存中只有一个值。
缺点:
1. 不能取指定值不如索引灵活,并且迭代器是一次性的。
2. 无法预知迭代器数据的个数。
'''
# 可迭代的对象: str,list,tuple,dict,set,文件对象。
# 迭代器对象: 文件对象。
# 可迭代的对象=====》迭代器对象:调用可迭代对象内置的__iter__方法会有一个返回值,该返回值就是对应的迭代器对象。
dic={'x':1,'y':2,'z':3}
针对一个迭代器,用多个next方法取值:会迭代取到值。
# iter_dic=dic.__iter__()
# # print(iter_dic)
# res1=iter_dic.__next__()
# print(res1)
#
# res2=iter_dic.__next__()
# print(res2)
#
# res3=iter_dic.__next__()
# print(res3)
#
# res4=iter_dic.__next__()
# print(res4) 》》》报错stopitnation!!
针对多个迭代器用next方法取值:都是取到同一个值。
iter_dic=dic.__iter__()
iter_dic=dic.__iter__()
iter_dic=dic.__iter__()#得到3个迭代器。
# print(iter_dic.__next__())
# print(iter_dic.__next__())
# print(iter_dic.__next__())
或者这样写:与上面意思一样。
# print(dic.__iter__().__next__())
# print(dic.__iter__().__next__())
# print(dic.__iter__().__next__())
# dic={'x':1,'y':2,'z':3}
# # dic=['a','b','c']
# iter_dic=dic.__iter__()
#
# # iter_dic=open(r'D:\上海python全栈4期\day13\今日内容',mode='rt',encoding='utf-8')
#
# while True:
# try:
# print(iter_dic.__next__())
# except StopIteration:
# break
# for准确地说应该是迭代器循环,for循环的原理如下:
#1. 先调用in后面那个值的__iter__方法,得到迭代器对象;
#2. 执行迭代器.__next__()方法得到一个返回值,然后赋值给一个变量k,运行循环体代码;’
#3, 循环往复,直到迭代器取值完毕抛出异常然后,自动捕捉异常结束循环。
dic={'x':1,'y':2,'z':3}
iter_dic=dic.__iter__()
print(iter_dic)
print(iter_dic.__iter__())
# for k in dic: #iter_dic=dic.__iter__()
# print(k)
# with open(r'D:\上海python全栈4期\day13\今日内容',mode='rt',encoding='utf-8') as f:
# for line in f: #iter_f=f.__iter__()
# print(line)
#yield关键字:只能用在函数内!
# 在函数内但凡包含有yield关键字,再去执行函数,就不会立刻运行函数体代码了。
# 生成器函数会得到一个返回值,该返回值成之为生成器对象,生成器本质就是迭代器。
# 总结yield:
# 1. 提供一种自定义迭代器的解决方案!
# 2. yield可用于返回值。
# yield VS return
# 相同点:都可以用于返回值不限制出现的个数,不限制值的类型和几个。
# 不同点:yield可以暂停函数,yield可以返回多次值,而return只能返回值一次值函数就立刻终止
# def func():
# print('=====>第一次')
# yield 1
# print('=====>第二次')
# yield 2
# print('=====>第三次')
# yield 3
# print('=====>第四次')
#
# # print(func)
#
# g=func()
# # print(g.__iter__().__iter__().__iter__() is g)
# # iter(g) #g.__iter__()
# # next(g) #g.__next__()
#
# res1=next(g)
# print(res1)
#
# res2=next(g)
# print(res2)
#
# res3=next(g)
# print(res3)
#
# res4=next(g)
# print(res4)
def my_range(start,stop,step=1):
while start < stop:
yield start
start+=step
res=my_range(1,5,2) # 1 3
next(res)
next(res)
# print(next(res))
# for item in res:
# print(item)
for item in my_range(1,5,2):
print(item)
# 三元表达式
三元表达式基本形式:
res=条件成立的值(可以是一个或多个值逗号隔开) if条件 条件不成立的值(同前)
# def max2(x,y):
# if x > y:
# return x
# else:
# return y
#
# x=10
# y=20
# res='条件成立的值' if x > y else '条件不成立的值'
# print(res)
# 列表生成式
# l=[]
# for i in range(1,11):
# if i > 4:
# res='egg%s' %i
# l.append(res)
# print(l)
#
# l=['egg%s' %i for i in range(1,11) if i > 4]
# print(l)
上面意思:for循环一次取到一个值给i,判断一次,符合条件就加入列表,不符合不加入,这样的操作执行多次。
# names=['egon','lxx','yyx','cw','alex','wxx']
# l=[]
# for name in names:
# if name != 'egon':
# res='%s_DSB' %name
# l.append(res)
# print(l)
#
# l=['%s_DSB' %name for name in names if name != 'egon']
# print(l)
# 生成器表达式
# res=(i**2 for i in range(3))
# print(res)
# print(next(res))
# print(next(res))
# print(next(res))
# print(next(res))
with open(r'D:\上海python全栈4期\day13\今日内容',mode='rt',encoding='utf-8') as f:
# data=f.read()
# print(len(data)) #1025
# res=0
# for line in f:
# res+=len(line)
# print(res)
# res=sum((len(line) for line in f))
# res=sum(len(line) for line in f)
# print(res)
# res=max([len(line) for line in f])
# res=max((len(line) for line in f))
res=max(len(line) for line in f)
print(res)
# 字典生成式
# items=[('name','egon'),('age',18),('sex','male')]
# dic={}
# for k,v in items:
# dic[k]=v
# print(dic)
# res={k:v for k,v in items if k != 'sex'}
# print(res)
# res={i for i in 'hello'}
# print(res)

浙公网安备 33010602011771号