1、有参装饰器
''' import time current_user={'user':None} def deco(func): def wrapper(*args,**kwargs): if current_user['user']: #已经登陆过 res = func(*args, **kwargs) #用户已经登录直接调用被装饰的函数,不需要重复进行登录 return res user=input('username>>: ').strip() pwd=input('password>>: ').strip() if user == 'egon' and pwd == '123': print('login successful') # 记录用户登陆状态 current_user['user']=user #登录成功记录用户的登录状态,然后调用被装饰的函数 res=func(*args,**kwargs) return res else: print('user or password error') return wrapper @deco def index(): print('welcome to index page') time.sleep(1) @deco def home(name): print('welecome %s to home page' %name) time.sleep(0.5) index() home('egon') ''' # def f1(): # x=1 # def f2(): #装饰器外在套一层函数,通常最多套三层 # def f3(): # print(x) # return f3 # return f2 # # f2=f1() # # f3=f2() # # f3() import time current_user={'user':None} #记录用户的登录状态 def auth(engine='file'): #接收函数体内部需要外部传入的参数 def deco(func): #func接收被装饰的函数不能改 def wrapper(*args,**kwargs): #wrapper(*args,**kwargs)接收被装饰函数的的参数 if current_user['user']: #记录用户的登录状态,判断用户是否已经登录 #已经登陆过 res = func(*args, **kwargs) #用户已经登录,则会直接调用被装饰的函数 return res #拿到被装饰函数的返回值,没有返回值则返回None user=input('username>>: ').strip() pwd=input('password>>: ').strip() if engine == 'file': #engine即为需要最外层函数传入的值,否则会报错 # 基于文件的认证 if user == 'egon' and pwd == '123': print('login successful') # 记录用户登陆状态 current_user['user']=user #记录用户的登录成功后的状态 res=func(*args,**kwargs) #登录成功后调用被装饰的函数 return res #拿到被装饰函数的返回值 else: print('user or password error') elif engine == 'mysql': print('基于mysql的认证') elif engine == 'ldap': print('基于ldap的认证') else: print('无法识别认证来源') return wrapper return deco @auth(engine='file') # @deco #index=deco(index) #index=wrapper def index(): print('welcome to index page') time.sleep(1) @auth(engine='file') def home(name): print('welecome %s to home page' %name) time.sleep(0.5) index() home('egon')
2、迭代器
''' 1、什么是迭代器 迭代器即迭代取值的工具 迭代: 迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的 单纯的重复并不是迭代 while True: print('1111') #单纯的重复没有基于上一次的结果 迭代: l=['a','b','c'] def iterator(item): i=0 while i < len(item): print(l[i]) i+=1 2、 为什么要有迭代器 基于索引的迭代器取值方式只适用于列表、元组、字符串类型 而对于没有索引的字典、集合、文件,则不在适用 所以必须找到一种通用的并且不依赖于索引的迭代器取值方式=》迭代器 迭代器适用于可迭代的类型 3、如何用迭代器 ''' # l=['a','b','c'] # i=0 # while i < len(l): #使用while条件循环,每次基于上一次的结果而来,所以是迭代 # print(l[i]) # i+=1 # l = ['a', 'b', 'c'] # s='hello' # # def iterator(item): #item='hello' #将重迭代的过程,定义成一个函数,每次取不同数据类型的值,只需要传参调用即可 # i = 0 # while i < len(item): # print(item[i]) # i += 1 # # iterator(l) #将列表当做参数传入调用 # iterator(s) #将字符串当做参数传入调用 # 可迭代的对象:在python中但凡内置有__iter__方法的对象都是可迭代的对象 # 字符串、列表、元组、字典、集合、文件都是可迭代的对象 # num1=10 # num2=10.1 # s1='hello' # l=[1,2,3] # t=(1,2,3) # d={'x':1} # s2={1,2,3} # f=open('a.txt','w') # # s1.__iter__ #以下数据类型及文件均内置有__iter__,所以都是可迭代对象 # l.__iter__ # t.__iter__ # d.__iter__ # s2.__iter__ # f.__iter__ # # # 迭代器对象:指的是既内置有__iter__方法,又内置有__next__方法的对象 #执行可迭代对象的__iter__方法得到的就是内置的迭代器对象 # 文件对象--------------------------本身就是迭代器对象 #强调: #1、迭代器对象一定是可迭代的对象,反之则不然 # info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'} # info_iter=info.__iter__() #---------执行__iter__()方法。得到的是迭代器对象 # print(info_iter) #---------<dict_keyiterator object at 0x0000010BDC4110E8>字典的key值迭代器对象 # res1=info_iter.__next__() #---------迭代器对象执行__next__()方法,取出可迭代对象中的一个值 # print(res1) #---------name # res2=info_iter.__next__() # print(res2) #---------age # # res3=info_iter.__next__() # print(res3) #---------is_beautiful # # res4=info_iter.__next__() # print(res4) #---------sex # # info_iter.__next__() # 一旦迭代器取值取干净,再继续取就会抛出StopIteration # info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'} # # info=[1,2,3,4,5] # info_iter=info.__iter__() # while True: # try: # print(info_iter.__next__()) # except StopIteration: #判断抛出的异常是不是StopIteration,是则执行break # break #for循环:迭代器循环 # info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'} #in后跟的一定要是可迭代的对象 # for k in info: # info_iter=info.__iter__() # print(k) # f=open('a.txt','r') # for k in f: # print(k) #基于for循环,我们可以完全不再依赖索引去取值了 # dic={'a':1,'b':2,'c':3} # for k in dic: # print(dic[k]) #for循环的工作原理 #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码 #3: 重复过程2,直到捕捉到异常StopIteration,结束循环 # 总结: # 迭代器对象:指的是既内置有__iter__方法,又内置有__next__方法的对象 # 执行迭代器对象的__next__得到的是迭代器的下一个值 # 执行迭代器对象的__iter__得到的仍然是迭代器本身 # iter_info=info.__iter__() # # print(iter_info) # print(iter_info is iter_info.__iter__() is iter_info.__iter__().__iter__().__iter__().__iter__().__iter__()) #True # #总结迭代器对象的优缺点: #优点: #1、提供了一种通用的、可以不依赖索引的迭代取值方式 #2、迭代器对象更加节省内存 # f=open('movie.tar.gz','rb') # f.__ next__() # f=open('db.txt','rt',encoding='utf-8') # # print(f.__next__()) # print(f.__next__()) # print(next(f)) #f.__next__() # s='hello' # print(s.__len__()) # print(len(s)) # s.__iter__() # print(iter(s)) # 缺点: #1、迭代器的取值不如按照索引的方式更灵活,因为它只能往后取不能往前退 #2、无法预测迭代器值的个数 # names=['egon','alex_SB','wxx_SB'] #取出列表中的第二个值,只能一个一个的取,也不能统计出列表的长度,只有取完再取的时候才会抛出异常 # iter_names=iter(names) # print(next(iter_names)) # print(next(iter_names)) # # iter_names=iter(names) # print(next(iter_names)) # print(next(iter_names)) # # print(next(iter_names)) # # print(names[1]) #而使用索引则可以很方面的就取出列表中的第二个值 # print(names[1]) # s=set('helllllo') #将字符串转换成集合底层原理:就是先把字符串执行__iter__得到迭代器对象,迭代器对象在执行__next__方法,将值取出来放到集合中,直到值被取干净 # print(s) # for i in 10: #10不可迭代对象,底层原理走不通所以会报错,TypeError: 'int' object is not iterable # pass # list(10) #list底层原理也是for循环,所以放10也会包同样的错误,TypeError: 'int' object is not iterable # names=['a','b','c','d'] # iter_names=iter(names) #names.__iter__()可以改写成iter(names)两者是等价的 # # l1=list(iter_names) #将迭代器对象循环放入得到列表中 # print(l1) #['a', 'b', 'c', 'd'] # # l2=list(iter_names) #迭代器对象值已经全部放入到列表中,所以已经别取干净了,此时的列表为空列表 # print(l2) #[] # f=open('db.txt','rt',encoding='utf-8') # # print(list(f)) #文件本身就是迭代器对象,所以第一次已经把文件中的值全部取干净了,['11111111111111111 ', '2222222222222 ', '33333 ', '4444 ', '55555'] # print(list(f)) #[] #迭代器对象已经为空,所以得到的列表也均为空列表 # print(list(f)) #[] # print(list(f)) #[] # print(list(f)) #[] # l1=[1,2,3,] # diedaiqi=l1.__iter__() # print(list(l1)) #l1均为迭代器对象,循环将值放入到列表中的列表都会有值,[1, 2, 3] # print(list(l1)) #[1, 2, 3] # print(list(l1)) #[1, 2, 3] # print(list(l1)) #[1, 2, 3] # print(list(l1)) #[1, 2, 3] # print(list(l1)) #[1, 2, 3]