叠加多个装饰器、迭代器、自定义迭代器和xxx生成式
一、叠加多个装饰器
1、加载装饰器就是将原函数名偷梁换柱成了装饰器最内层那个wrapper函数
在加载完毕后,调用原函数其实就是在调用wrapper函数
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 successful')
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') #@xxx #index = xxx(最原始那个index的内存地址) #index = wrapper2的内存地址
def index():
print('welcome to index page')
time.sleep(2)
index() #wrapper1的内存地址()
二、迭代器
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__会得到迭代器本身
4、总结迭代器的优缺点:
优点:
1、提供了一种通用的&可以不依赖索引的迭代取值方式
2、同一时刻在内存中只有一个值,更加节省内存
缺点:
1、取指定值不如索引灵活,并且迭代器是一次性的
2、无法预知迭代器数据的个数
可迭代的对象:str,list,tuple,dict,set,文件对象
迭代器对象:文件对象
可迭代的对象====》迭代器对象:调用可迭代对象内置的__iter__方法会有一个返回值,该返回值
就是对应的迭代器对象
dic = {'x':1,'y':2,'z':3}
iter_dic= dic.__iter__()
res1 = iter_dic.__next__()
print(res1)
res2 = iter_dic.__next__()
print(res2)
print(dic.__iter__().__next__())
print(dic.__iter__().__next__()) #这样定义会重现产生一个可迭代对象,然后会打印x,是错误的~
迭代器打印文件内容:
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('a.txt',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('=========>第四次')
g = func()
#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)
自制一个range函数:
def my_rage(start,stop,step = 1)
while start < stop:
yield start
start+=step
res = my_range(1,5,2)
next(res)
next(res)
#print(next(res))
#for item in res:
#print(item)
for item in my_range(1,5,2):
print(item)
四、xxx生成式
1、三元生成式
def max2(x,y):
if x>y:
return x
else:
return y
x = 10
y = 20
res = '条件成立的值' if x>y else '条件不成立的值'
print(res)
2、列表生成式
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)
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)
3、生成器表达式
res = (i**2 for i in range(3))
print(res)
print(next(res))
print(next(res))
print(next(res))
print(next(res)) #因为是0-2 所以最多被调用三次 调用第四次的时候会报错
with open('a.txt',mode = 'rt',encoding = 'utf-8') as f:
data = f.read()
print(len(data))
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)
4、字典生成式
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)
5、集合生成式
res = {i for i in 'hello'}
print(res)