zoukankan      html  css  js  c++  java
  • 装饰器和迭代器

    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

  • 相关阅读:
    Oracle之PL/SQL学习笔记
    Git常用命令
    Web前端上万字的知识总结
    Objective-C中小怪兽的逻辑
    PHP精选数组函数
    数据库连接字符串方法
    WM_CAP_DRIVER_CONNECT
    GB2312/ANSI编码转中文字符
    opencv播放不了AVI视频的问题
    我的MFC/C++学习笔记 http://blog.bccn.net/CrystalFan/6909
  • 原文地址:https://www.cnblogs.com/itone/p/9524567.html
Copyright © 2011-2022 走看看