• 18、有参函数和迭代器以及生成器


    一、有参函数

    1.1、装饰器的目标,即偷梁换柱之后

      1.原函数参数是什么样的,装饰器的参数就应该是什么样的

      2.原函数返回值是什么样的,装饰器的返回值就应该是什么样的

      3.原函数的属性是什么样的,装饰器的属性就行该是什么样的   #  from functools    import  wraps

    1.2、有参函数的使用

      在无参函数的基础上设定有参函数

    def auth(func,db_type):
        def wrapper(*args, **kwargs):       #
            name=input('your name>>>: ').strip()
            pwd=input('your password>>>: ').strip()
    
            if db_type == 'file':              
                print('基于文件的验证')
                if name == 'egon' and pwd == '123':
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('user or password error')
            elif db_type == 'mysql':
                print('基于mysql的验证')
            elif db_type == 'ldap':
                print('基于ldap的验证')
            else:
                print('不支持该db_type')
    
        return wrapper           #在无参函数的基础上添加了判断条件,并且判断条件需要从其他函数里面调用
    
    # @auth  # 账号密码的来源是文件
    def index(x,y):
        print('index->>%s:%s' %(x,y))
    
    # @auth # 账号密码的来源是数据库
    def home(name):
        print('home->>%s' %name)
    
    # @auth # 账号密码的来源是ldap
    def transfer():
        print('transfer')
    
    
    index=auth(index,'file')         #函数的启动
    home=auth(home,'mysql')
    transfer=auth(transfer,'ldap')
    
    # index(1,2)               #给函数赋值
    # home('egon')
    # transfer()

    1.3、对函数进行优化,修改函数体。添加新函数,值为条件。原函数后退一格,末尾加return  值为上一个内函数。

    def auth(db_type):          #新增函数,在无参函数的外围在逃一个函数,用来添加条件      函数内的值填为条件
        def deco(func):        #将所有函数进行后退一格
            def wrapper(*args, **kwargs):
                name=input('your name>>>: ').strip()
                pwd=input('your password>>>: ').strip()
    
                if db_type == 'file':           #添加的条件
                    print('基于文件的验证')
                    if name == 'egon' and pwd == '123':
                        res = func(*args, **kwargs)
                        return res
                    else:
                        print('user or password error')
                elif db_type == 'mysql':
                    print('基于mysql的验证')
                elif db_type == 'ldap':
                    print('基于ldap的验证')
                else:
                    print('不支持该db_type')
    
            return wrapper
        return deco                       #添加return  值为之前的函数
    
    deco=auth(db_type='file')
    @deco # 账号密码的来源是文件
    def index(x,y):
        print('index->>%s:%s' %(x,y))
    
    deco=auth(db_type='mysql')
    @deco # 账号密码的来源是数据库
    def home(name):
        print('home->>%s' %name)
    
    deco=auth(db_type='ldap')
    @deco # 账号密码的来源是ldap
    def transfer():
        print('transfer')
    
    
    index(1,2)
    home('egon')
    transfer()

    1.4、对函数进行优化,修改被装饰函数的启动项,@最后一层函数,内部条件为判断条件

    def auth(db_type):    # 插入新函数,值为参数
        def deco(func):          #后退一格
            def wrapper(*args, **kwargs):    
                name=input('your name>>>: ').strip()     #函数体
                pwd=input('your password>>>: ').strip()
    
                if db_type == 'file':           #新增判断条件,即新增参数
                    print('基于文件的验证')
                    if name == 'egon' and pwd == '123':
                        res = func(*args, **kwargs)
                        return res
                    else:
                        print('user or password error')
                elif db_type == 'mysql':
                    print('基于mysql的验证')
                elif db_type == 'ldap':
                    print('基于ldap的验证')
                else:
                    print('不支持该db_type')
    
            return wrapper       #return  由于缩进,导致原参数只能返回到局部。将原本需要输出的值返回全局,不改变原来的状态    值为前一个函数
        return deco
       #将两个函数触发项进行合并
    @auth(db_type='file')  # @deco # index=deco(index) # index=wrapper
    def index(x, y):
        print('index->>%s:%s' % (x, y))
    
    @auth(db_type='mysql')  # @deco # home=deco(home) # home=wrapper
    def home(name):
        print('home->>%s' % name)
    
    
    @auth(db_type='ldap')  # 账号密码的来源是ldap
    def transfer():
        print('transfer')
    
    
    index(1,2)
    home('egon')
    transfer()

    1.5、有参函数模板

    def 有参装饰器(x,y,z):
        def outter(func):
            def wrapper(*args, **kwargs):
                res = func(*args, **kwargs)
                return res
            return wrapper
        return outter
    
    @有参装饰器(1,y=2,z=3)
    def 被装饰对象():
        pass

    二、迭代器

    2.1、 什么是迭代器

      迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复是基于上一次重复的结果

    2.2、为什么要有迭代器

      迭代器使用来迭代取值的工具,涉及到循环的过程

      可以使用的类型有:列表、字符串、元组、字典、集合、打开文件

      while只能在有序的类型中使用,因此python需要一种任意类型都能使用取值的方式,即for的使用原理

    2.3、怎么使用迭代器

    2.3.1、使用__iter__的方式来使用迭代器

    # 1、可迭代的对象:但凡内置有__iter__方法的都称之为可迭代的对象
    # s1=''
    # # s1.__iter__()  

    2.3.2、使用——next——的方式的带迭代器对象

    # 2、调用可迭代对象下的__iter__方法会将其转换成迭代器对象
    d={'a':1,'b':2,'c':3}
    d_iterator=d.__iter__()     #将列表d加入迭代器
    # print(d_iterator)
    
    # print(d_iterator.__next__())   输出迭代器的值
    # print(d_iterator.__next__())
    # print(d_iterator.__next__())
    # print(d_iterator.__next__()) # 抛出异常StopIteration,迭代器里面无值

    2.4、可迭代对象和迭代器对象的区别

      可迭代对象:(可以转换成跌迭器的对象):内置有__iter__的对象

      迭代器对象:同时存在__iter__以及——next——的对象

            ——next——会返回迭代器下一个值,而——iter——返回迭代器本身

    2.5、可迭代对象和迭代器对象的范围

      可迭代对象:列表、字符串、元组、字典、集合、文件对象

      迭代器对象:文件对象

    2.6、for循环的原理,即迭代器循环

      for循环分为三步:

      1.先使用迭代器d.__iter__()得到对象

      2.使用迭代器对象__iter__()得到返回值,然后赋值给k

      3.最后重复第二步,直到迭代器的值全部输出后报错

    for k in d:
        print(k)
    with open('a.txt',mode='rt',encoding='utf-8') as f:
        for line in f: # f.__iter__()
            print(line)
    list('hello') #原理同for循环

    2.7、迭代器的优缺点

      优点:为所有类型都提供了一对一取值的方式

         惰性计算:迭代器对象表示的是一个数据流,只有在调用next的时候才能计算出一个值,同一时刻内存中只存在一个值,因此可以存放无限大的数据流

      缺点:除非取尽数据,否则无法算出迭代器的长度

         只能取一个值,不能重新开始,除非取尽否则会一直停留在原地

         若使用多个函数使用一个迭代器取值,只有一个能生效。

    三、生成器

    3.1、怎么自定义生成器

      使用yield返回迭代器对象,不会像return一样退出,生成器就是迭代器

    def func():
        print('第一次')
        yield 1
        print('第二次')
        yield 2
        print('第三次')
        yield 3
        print('第四次')     
    g=func()
    print(g)

    3.2、举例:

    def my_range(start,stop,step=1):
        print('start...')
        while start < stop:
            yield start
            start+=step
        print('end....')
    g=my_range(1,5,2) # 1 3
    print(next(g))
    print(next(g))
    print(next(g))     #需要使用next来执行下一次操作

     3.3、多个装饰器的加载  (了解)

      加载时从下到上进行加载,执行时从上到下开始执行

    def deco1(func1): # func1 = wrapper2的内存地址
        def wrapper1(*args,**kwargs):
            print('正在运行===>deco1.wrapper1')
            res1=func1(*args,**kwargs)
            return res1
        return wrapper1
    
    def deco2(func2): # func2 = wrapper3的内存地址
        def wrapper2(*args,**kwargs):
            print('正在运行===>deco2.wrapper2')
            res2=func2(*args,**kwargs)
            return res2
        return wrapper2
    
    def deco3(x):
        def outter3(func3): # func3=被装饰对象index函数的内存地址
            def wrapper3(*args,**kwargs):
                print('正在运行===>deco3.outter3.wrapper3')
                res3=func3(*args,**kwargs)
                return res3
            return wrapper3
        return outter3
    
    
    # 加载顺序自下而上(了解)
    @deco1      # index=deco1(wrapper2的内存地址)        ===> index=wrapper1的内存地址
    @deco2      # index=deco2(wrapper3的内存地址)        ===> index=wrapper2的内存地址
    @deco3(111) # ===>@outter3===> index=outter3(index) ===> index=wrapper3的内存地址
    def index(x,y):
        print('from index %s:%s' %(x,y))
    
    # 执行顺序自上而下的,即wraper1-》wrapper2-》wrapper3
    index(1,2) # wrapper1(1,2)
  • 相关阅读:
    jQuery实现选项联动轮播
    EasyUI datagrid 行编辑
    UEditor的使用
    jQuery Pagination分页插件的使用
    SQL Server论坛楼层计算触发器
    编写了一个简单的串口映射工具
    JS表单验证插件(支持Ajax验证)
    JS虚拟键盘
    JS数字键盘
    HTML的select控件美化
  • 原文地址:https://www.cnblogs.com/jingpeng/p/12562485.html
Copyright © 2020-2023  润新知