zoukankan      html  css  js  c++  java
  • 016.Python之有参装饰器与迭代器

    一、装饰器补充:有参装饰器

    (一)什么是有参装饰器

    在无参装饰器两层装饰的基础上,再增加一层函数,用于传递一个新的参数,这个装饰器就是一个有参装饰器。

    (二)为何要用有参装饰器

    无参装饰器实现了与原函数一样的调用方式,并通过闭包函数实现了原函数参数不被改变,当我们需要一个新的功能,而这个新的功能又需要一个参数的时候,无参装饰器就无法满足装饰器的原则,因此需要有参装饰器去实现这个功能。

    # 无参装饰器  两层闭包无法给被装饰函数传递该函数本身需要参数之外的值
    import time
    
    def outter(func):
        def wrapper(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            stop = time.time()
            print(stop - start)
            return res
        return wrapper
    
    # @函数的内存地址1(1,2,3,4,5)  # @的作用是给函数的内存地址加括号,调用函数index
    def index(x, y):
        print('index===>', x, y)
    
    @outter
    def home(name):
        print('home====>', name)
    
    # 引出两个点:
    # 1、可以通过闭包的方式为函数体传参,可以包一层,也可以包两层
    # 2、@后跟的必须是一个函数的内存地址,@函数的内存地址(1,2,3) 是可以的,但是前提是调用函数"函数的内存地址(1,2,3)"的返回值必须是一个函数的内存地址
    

    (三)有参装饰器如何使用

    通过示例,演示有参装饰器的实现。

    1.示范一

    # 示范一: 无参装饰器
    def outter(func):
        def wrapper(*args, **kwargs):
            inp_name = input("please input your username: ").strip()
            inp_pwd = input("please input your password: ").strip()
            with open("db.txt",mode="rt",encoding="utf-8") as f:
                for line in f:
                    name_db, pwd_db, balance_db = line.strip("
    ").split(":")
                    if inp_name == name_db and inp_pwd == pwd_db:
                        print("login successful")
                        res = func(*args, **kwargs)
                        return res
                else:
                    print("login failed")
    
        return wrapper
    
    @outter
    def index(x, y):
        print('index===>', x, y)
    
    index(1, 2)
    

    2.示范二

    # 示范二:增加用户验证数据的多个来源
    # ldap
    # mysql
    # file
    def outter2(mode):
        def outter(func):
            def wrapper(*args, **kwargs):
                inp_name = input("please input your username: ").strip()
                inp_pwd = input("please input your password: ").strip()
                if mode == "file":
                    print("认证来源=====》file")
                    with open("db.txt",mode="rt",encoding="utf-8") as f:
                        for line in f:
                            name_db, pwd_db, balance_db = line.strip("
    ").split(":")
                            if inp_name == name_db and inp_pwd == pwd_db:
                                print("login successful")
                                res = func(*args, **kwargs)
                                return res
                        else:
                            print("login failed")
                elif mode == "mysql":
                    print("认证来源=====》mysql")
                elif mode == "ldap":
                    print("认证来源=====》ldap")
                else:
                    print("未知认证来源")
    
            return wrapper
        return outter
    
    outter = outter2(mode="mysql")
    
    @outter  #语法糖@触发加括号运行 outter(index)=index ====》index = wrapper
    def index(x, y):
        print('index===>', x, y)
    
    index(1, 2)
    

    3.示范三

    # 示范三:语法糖加载方式简化
    def outter2(mode):
        def outter(func):
            def wrapper(*args, **kwargs):
                inp_name = input("please input your username: ").strip()
                inp_pwd = input("please input your password: ").strip()
                if mode == "file":
                    print("认证来源=====》file")
                    with open("db.txt",mode="rt",encoding="utf-8") as f:
                        for line in f:
                            name_db, pwd_db, balance_db = line.strip("
    ").split(":")
                            if inp_name == name_db and inp_pwd == pwd_db:
                                print("login successful")
                                res = func(*args, **kwargs)
                                return res
                        else:
                            print("login failed")
                elif mode == "mysql":
                    print("认证来源=====》mysql")
                elif mode == "ldap":
                    print("认证来源=====》ldap")
                else:
                    print("未知认证来源")
    
            return wrapper
        return outter
    
    
    
    @outter2(mode="mysql")  # outter2(mode="mysql")就是返回值outter,语法糖@触发加括号运行 outter(index)=index ====》index = wrapper
    def index(x, y):
        print('index===>', x, y)
    
    index(1, 2)  # wrapper(1, 2)
    

    二、迭代器

    (一)什么是迭代器

    迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的,但迭代不是单纯的重复。

    而迭代器,是一种迭代取值的工具,这种取值方式是通用的,不依赖于索引。

    (二)为什么要有迭代器

    迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型有:列表(索引取值)、字符串(索引取值)、元组(索引取值)、字典(key取值)、集合(既没key也没索引)、f文件对象(既没key也没索引)等。

    t = (111, 222, 333, 444, 555, 666)
    i = 0
    while i < len(t):  
        print(t[i])
        i += 1	
    

    上述使用while循环迭代取值的方式只适用于有索引的数据类型:列表、字符串、元组,为了解决基于索引迭代器取值的局限性,python提供了一种能够不依赖于索引的取值方式,这就是迭代器。

    (三)如何使用迭代器

    1.可迭代对象(iterable)

    从语法形式上讲,内置有 ._ _ iter _ _ ()方法的对象都是可迭代对象,字符串、列表、元组、字典、集合、打开的文件对象f都是可迭代对象,

    s = "hello"
    s.__iter__()
    
    l = [111, 222, 333]
    l.__iter__()
    
    t = (1111, 222, 333, 444, 555, 666)
    t.__iter__()
    
    d = {"k1": 111, "k2": 222, "k3": 3333}
    d.__iter__()
    
    s1 = {'a', 'b', 'c'}
    s1.__iter__()
    
    f = open(r'db.txt', mode='rt', encoding='utf-8')
    f.__iter__()
    f.close()  # 文件关闭后则无法调用,会报错
    

    2.迭代器对象

    调用 ._ _ iter _ _()返回的是迭代器对象。

    d = {"k1": 111, "k2": 222, "k3": 3333}
    res = d.__iter__()  # res=iter(d)
    print(res) # res是迭代器  <dict_keyiterator object at 0x00000240CD17B860>
    a = res.__next__()  # a=next(res)
    b = res.__next__()  # b=next(res)
    c = res.__next__()  # c=next(res)
    d = res.__next__()  # StopIteration
    
    # 此时,引入try-except 语句,进行异常监控, 提供处理异常的机制
    d = {"k1": 111, "k2": 222, "k3": 3333}
    
    iter_d = iter(d)  # 制造一个迭代器
    
    while True:
        try:
            print(next(iter_d))
        except StopIteration:
            break  # 此时,可以取出字典内所有的key值
    
    # 在一个迭代器取值取干净的情况下,再对其取值取不到,除非再次制造一个迭代器
    
    iter_d = iter(d)   # 再次制造一个迭代器
    while True:
        try:
            print(next(iter_d))
        except StopIteration:
            break  
    

    文本文件可循环的原理:

    f = open(r'db.txt', mode='rt', encoding='utf-8')
    line=f.__next__()
    print(line)  # aaa:123:11
    line=f.__next__()
    print(line)  # bbb:123:222
    for line in f:
        print(line)
    
    f.close()
    line=f.__next__() # 报错 ValueError: I/O operation on closed file.
    

    3.可迭代对象与迭代器对象详解

    # 可迭代的对象:有__iter__内置方法的对象都是可迭代的对象,str、list、tuple、dict、set、文件对象
    #            ps:可迭代对象.__iter__()返回的是迭代器对象
    
    # 迭代器对象:
    #          1、有__next__方法
    #          2、有__iter__方法,调用迭代器的__iter__方法得到的就是迭代器自己
    #          ps:迭代器对象之所内置__iter__方法是为了符合for循环第一个工作步骤
    
    d = {"k1": 111, "k2": 222, "k3": 3333}
    res=d.__iter__()
    
    print(res)  # <dict_keyiterator object at 0x0000022AFD9E4770>
    print(res.__iter__())  # <dict_keyiterator object at 0x0000022AFD9E4770>
    print(res.__iter__() is res)  # True  调用迭代器的__iter__方法得到的就是迭代器自己
    print(res.__iter__().__iter__().__iter__() is res)  # True
    

    (四)for循环的工作原理

    for循环可以称之为叫迭代器循环

    d = {"k1": 111, "k2": 222, "k3": 3333}
    
    for k in d:
        print(k)  
    
    for循环的工作步骤
    1、调用in后的对象的__iter__方法,得到对应的迭代器
    2、k=next(迭代器),然后执行一次循环
    3、循环往复,知道把迭代器的值取干净了,抛出异常,for循环会自动捕捉异常,结束循环
    

    (五)迭代器的优缺点

    1.优点:

    (1)不依赖索引,是一种通用的取值方式

    (2)节省内存

    d = {"k1": 111, "k2": 222, "k3": 3333}
    iter_d=iter(d)
    
    next(iter_d) 
    

    2.缺点:

    (1)不能取指定位置的值

    (2)不能预估值的个数,无法统计长度

    ll = [111, 222, 333]
    print(ll[2])  # 333
    
    iter_ll=iter(ll)
    next(iter_ll)
    next(iter_ll)
    print(next(iter_ll))  # 333
    
  • 相关阅读:
    CodeBlocks背景主题的设置
    Win7更改默认打开方式失败
    BAT命令介绍【转自Internet】
    Index of my articles
    一个表格说明RelativeLayout中的几个重要属性【Written By KillerLegend】
    有史以来最简单的三层实例(C#) ——转载自CSDN
    银联规定的MAC算法_转载
    Windows下ORACLE 10g安装与操作图解
    Oracle 在64位机器上使用PLSQL连接Oracle的问题(SQL * NET not properly installed)转载
    Linux系统下JDK和Tomcat安装配置
  • 原文地址:https://www.cnblogs.com/huluhuluwa/p/13178780.html
Copyright © 2011-2022 走看看