装饰器和迭代器

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)

Alt text

4. 迭代器对象

  • 可以被next调用并不断返回下一个值的对象称为迭代器
  • 迭代器对象:既可使用.__iter__()方法,又可以使用.__next__()方法的对象
  • 可迭代对象只有先使用.__iter__()转化为迭代器对象,迭代器对象才能执行.__next__()
  • 迭代器对象,执行.__next__()后,得到的是迭代器的下一个值
  • 迭代器对象执行__iter__()得到仍然是迭代器对象本身
  • 文件本身就是迭代器对象

  • 没有索引的取值,内置方法

Alt text

  • 一旦迭代器取完值,再继续取,就会出现以上提示StopIteration

Alt text

  • 不依赖索引,可以使用一下tryexcept来解决值取完了的情况
  • 直到出现StopIteration提示,停止循环。的异常,停止循环后,会继续后面的代码,不会影响后续代码执行

Alt text

Alt text

5. .__iter__().__next__()的区别

Alt text

  • .__iter__()只能被.__next__()循环一遍
  • .__iter__().__next__()重复循环后,只能得到空

例子一:

  • .__iter__()得到的迭代器对象,被.__next__()不断取值,直到取完,至此一次迭代器使用完毕
  • 如果再执行.__next__(),相当于在同一个迭代器中取值,只能取到空
  • name_iterf的身份就是迭代器对象,只能进行一次.__next__()循环
  • 一次迭代器对象,只能使用一次

Alt text

Alt text

  • 迭代器对象就是一个内存地址,只有配合next才能使用
  • 只有迭代器对象,才能被取空,可迭代对象可以重复取

例子二:

  • 例子二中,每次print,迭代器会重新执行一遍,相当于迭代器重新执行 .__iter__().__next__()
  • .__next__()处理的新的 .__iter__()迭代器对象
    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator????

Alt text

Alt text

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()都遵循迭代器协议

Alt text

原文地址:https://www.cnblogs.com/itone/p/9524567.html