一、多个装饰器
1、当一个被装饰的对象同时叠加多个装饰器时规则:
(1) 装饰器的加载顺序是:自下而上
(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') #@xxx #index=xxx(最原始那个index的内存地址) #index=wrapper2的内存地址 def index(): print('welcome to index page') time.sleep(2) index() #wrapper1的内存地址()
===================================>wrapper1运行了
===================================>wrapper2运行了
username>>>: egon
password>>>: 123
基于文件的认证
login successfull
welcome to index page
run time is 24.573405742645264
二、迭代器
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. 无法预知迭代器数据的个数
ps:
# 可迭代的对象: str,list,tuple,dict,set,文件对象
# 迭代器对象: 文件对象
# 可迭代的对象=====》迭代器对象:调用可
for准确地说应该是迭代器循环,for循环的原理如下:
#1. 先调用in后面那个值的__iter__方法,得到迭代器对象
#2. 执行迭代器.__next__()方法得到一个返回值,然后赋值给一个变量k,运行循环体代码
#3, 循环往复,直到迭代器取值完毕抛出异常然后捕捉异常自动结束循环
5、生成器
#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)
res1=next(g)
print(res1) =====>第一次 1
res2=next(g)
print(res2) =====>第二次 2
res3=next(g)
print(res3) =====>第三次 3
res4=next(g)
print(res4) =====>第四次 4
6、三元表达式
# def max2(x,y):
# if x > y:
# return x
# else:
# return y
#
# x=10
# y=20
# res='条件成立的值' if x > y else '条件不成立的值'
# print(res)
7、列表生成式
列表生成式
# 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)
8生成器表达式
# res=(i**2 for i in range(3))
# print(res)
# print(next(res)) 0
# print(next(res)) 1
# print(next(res)) 4
# print(next(res)) 报错
9、字典生成式
# 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)