Day7:有参装饰器、迭代器

it2022-05-19  85

一.有参装饰器

昨天的作业当中,做一个认证的装饰器,认证成功一次,执行其他函数不再进行认证。使用的装饰器为无参装饰器。

db_path=r'E:\PycharmProjects\qz5\db.txt' user_dic={ 'egon':'123', 'alex':'alex3714', 'wupeiqi':'123', 'yunahao':'123', } with open(db_path,'w',encoding='utf-8') as f: f.write(str(user_dic)) login_dic={ 'user':None, 'status':False, } def auth(func): #装饰器没有传入参数 def wrapper(*args,**kwargs): with open(db_path,'r',encoding='utf-8') as f: user_dic=eval(f.read()) while not login_dic['user'] and not login_dic['status']: name = input('name:') pwd = input('password:') if name in user_dic: if pwd==user_dic[name]: print('login successful') login_dic['user']=name login_dic['status']=True res=func(*args,**kwargs) return res else: print('password err') continue else:print('no user') else: res = func(*args, **kwargs) return res return wrapper @auth def index(): print('welcome to index') @auth def home(name): print('welcome %s to home page'%name) index() home('egon')

有不通的认证方式:比如ldap认证,mysql认证。现在要求不同的函数要用不通的认证方式,就需要用有参装饰器。有参装饰器也就是在无参装饰器外面再包一层函数,带上参数。

def deco(auth_type='file'): def auth(func): def wrapper(*args,**kwargs): if auth_type == 'file': print('文件的认证方式') elif auth_type == 'ldap': print('ldap的认证方式') elif auth_type == 'mysql': print('mysql的认证方式') else: print('不知道的认证方式') return wrapper return auth @deco(auth_type='abc') def index(): print('welcome to index ') @deco() def home(name): print('welcome to %s home page' %name) index() home('egon') 运行结果: 不知道的认证方式 文件的认证方式

二.迭代器

1.迭代

迭代就是重复,下一次的重复是基于上一次的结果

2.迭代器

python为了提供一种不依赖于索引的迭代方式,python会为一些对象内置__iter__方法obj.__iter__称为可迭代的对象

可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如list、tuple、dict、set、str等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True

你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

迭代器的优点1:提供了一种不依赖于索引的取值方式2:惰性计算。节省内存

迭代器的缺点:1:取值不如按照索引取值方便2:一次性的。只能往后走不能往前退3:无法获取长度

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

for x in [1, 2, 3, 4, 5]: pass

实际上完全等价于:

# 首先获得Iterator对象: it = iter([1, 2, 3, 4, 5]) # 循环: while True: try: # 获得下一个值: x = next(it) except StopIteration: # 遇到StopIteration就退出循环 break

 

转载于:https://www.cnblogs.com/Vee-Wang/p/7028271.html


最新回复(0)