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

  • 相关阅读:
    215. Kth Largest Element in an Array
    214. Shortest Palindrome
    213. House Robber II
    212. Word Search II
    210 Course ScheduleII
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    206. Reverse Linked List
    sql 开发经验
  • 原文地址:https://www.cnblogs.com/itone/p/9524567.html
Copyright © 2011-2022 走看看