Python-14
一、有参装饰器
- 实现登录一次后,后续函数执行,不用再重复登录
import time
user_status={'user':None}
def deco(func):
def wrapper(*args,**kwargs):
# 如果登录了就不需要密码
if user_status['user']:
res=func(*args,**kwargs)
return res
user = input('user>>').strip()
passwd = input('passwd>>').strip()
if user == 'xdw' and passwd == '123':
print('login successful')
user_status['user']=user
res=func(*args,**kwargs)
return res
else:
print('login incorrect')
return wrapper
@(Python)deco
def index():
print('welcome index')
time.sleep(1)
index()
@deco
def home(name):
print('my name is %s' %name)
time.sleep(1)
home('xudawei')
- 装饰器传入参数
- 用户在登录不同的需求时,可能需要比对不同的用户密码文件,这就可以用到有参装饰器
import time
user_status={'user':None}
# 这里的参数相当于整个函数都可以使用,即局部名称空间中的数据
def auth(engine='file'): # 其实这一层可以传多个参数 def auth(engine='file',x=1,y=2):
def deco(func):
def wrapper(*args,**kwargs):
# 基于file的登录
if engine == 'file':
if user_status['user']:
res=func(*args,**kwargs)
return res
user_name=input('username>>>')
user_password=input('userpassword>>>')
if user_name == 'xut' and user_password == '123':
print('login succeful')
user_status['user']=user_name
res=func(*args,**kwargs)
return res
else:
print('login incorrect')
elif engine == 'mysql':
print('基于mysql的登录')
elif engine == 'ldap':
print('基于ldap的登录')
return wrapper
return deco
@auth(engine='file') # index=deco(index)==>deco(index)==>wrapper
def index():
print('welcome index')
time.sleep(1)
@auth(engine='mysql')
def home(name):
print('my name is %s' %name)
有参装饰器模板
def outter(x) # x参数可以在整个函数体内被使用
def deco(func) # func最原始的函数
def wrapper(*args,**kwargs)
res=func(*args,**kwargs)
return res
return wrapper
return deco
二、迭代器
1. 什么是迭代器
- 迭代:是一个重复的过程,每一次迭代都是基于上一次结果,单纯的重复并不是迭代
- 迭代器:就是迭代取值的工具
- 不同的取值方式:不依赖(不使用)索引的迭代器取值方式;基于索引的取值方式
- 使用
while
循环,基于索引的迭代取值方式
l=['a','b','c']
s='hello'
def iterator(item):
n = 0
while n < len(item):
print(item[n])
n+=1 iterator(s)
2. 为什么要有迭代器
- 迭代器可以取出可迭代对象的值
- 基于索引的迭代器取值方式:适用于列表、元组、字符串,不适用没有索引的字典、集合、文件
- 不依赖(不使用)索引的迭代器取值方式:属于通用取值方式,但是没有基于索引的灵活
3. 可迭代对象
- 可迭代对象:具备
.__iter__
内置方法的对象,就是可迭代对象- 迭代器对象:执行
.__iter__
后,得到的就是迭代器对象- 可迭代对象:字符串、列表、元组、字典、集合、文件(open);整型和浮点型不属于可迭代对象
info={'name':'xut','age':18,'sex':'male'}
info_iter=info.__iter__() # 得到的是内置的迭代器对象
print(info_iter)
4. 迭代器对象
- 可以被
next
调用并不断返回下一个值的对象称为迭代器- 迭代器对象:既可使用
.__iter__()
方法,又可以使用.__next__()
方法的对象- 可迭代对象只有先使用
.__iter__()
转化为迭代器对象,迭代器对象才能执行.__next__()
- 迭代器对象,执行
.__next__()
后,得到的是迭代器的下一个值- 迭代器对象执行
__iter__()
得到仍然是迭代器对象本身- 文件本身就是迭代器对象
- 没有索引的取值,内置方法
- 一旦迭代器取完值,再继续取,就会出现以上提示
StopIteration
- 不依赖索引,可以使用一下
try
和except
来解决值取完了的情况- 直到出现
StopIteration
提示,停止循环。的异常,停止循环后,会继续后面的代码,不会影响后续代码执行
5. .__iter__()
和.__next__()
的区别
.__iter__()
只能被.__next__()
循环一遍.__iter__()
被.__next__()
重复循环后,只能得到空
例子一:
.__iter__()
得到的迭代器对象,被.__next__()
不断取值,直到取完,至此一次迭代器使用完毕- 如果再执行
.__next__()
,相当于在同一个迭代器中取值,只能取到空name_iter
和f
的身份就是迭代器对象,只能进行一次.__next__()
循环- 一次迭代器对象,只能使用一次
- 迭代器对象就是一个内存地址,只有配合
next
才能使用- 只有迭代器对象,才能被取空,可迭代对象可以重复取
例子二:
- 例子二中,每次
.__iter__()
和.__next__()
.__next__()
处理的新的.__iter__()
迭代器对象
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator????
x_list
是一个真实的值,不是内存地址,可迭代对象可以使用多次,迭代器对象只能用一次
http://python.jobbole.com/87805/
6. for循环的工作原理
for
循环,又叫迭代器循环for
会自动调.__iter__()
,将可迭代对象转为可迭代器对象,因此能用for
循环的一定是可迭代对象- 变为迭代器对象后,for循环,会不断的使用
.__next__()
获取基于上一个结果的值
info={'name':'xut','age':18,'sex':'male'}
for i in info: # in后面跟的就是可迭代对象
print(i)
7. 迭代器对象的优缺点
① 迭代器优点:
- 提供了一种通用的,可以不依赖索引的迭代取值方式
- 迭代器对象取值方式,使用的是
.__next__()
,同一时间,在内存中只有一个值,更加节省内存空间(for循环的原理)
② 缺点:
- 迭代器的取值,不如按照索引的方式灵活,只能从前往后取,不能从后往前取
- 无法预测迭代器值的个数
③ 其他说明
.__next__()
执行一次,只能获取一个值,要获取多个值,就需要重复执行- 迭代器对象,一定是可迭代对象
- 可迭代对象,不一定是迭代器对象
8. 迭代器内置方法的书写格式
f.__next__()
可以写为:next(f)
f.__iter__()
可以写为:iter(f)
9. 迭代器协议
- 迭代器协议:将可迭代对象,变为迭代器对象,然后不断的
.__next__()
取值list()
tuple()
set()
都遵循迭代器协议