叠加多个装饰器、迭代器、自定义迭代器和xxx生成式

  叠加多个装饰器、迭代器、自定义迭代器和xxx生成式

  一、叠加多个装饰器

    1、加载装饰器就是将原函数名偷梁换柱成了装饰器最内层那个wrapper函数

      在加载完毕后,调用原函数其实就是在调用wrapper函数

    2、当一个被装饰的对象同时叠加多个装饰器时

      装饰器的加载顺序是:自下而上

      装饰器内wrapper函数的执行顺序是:自上而下

    例子:

      import time

      def timmer(func):  #func = wrapper2的内存地址

        def wrapper1(*args,**kwargs):

          print('================>wrapper1运行了')

          start = time.time()

          res = func(*args,**kwargs)  #===================>跳到wrapper2去执行了

          stop = time.time()

          print('run time is %s'%(stop-start))

          return res

        return wrapper1

      

      def auth(engine='file'):

        def xxx(func):  #func = 最原始那个index的内存地址

          def wrapper2(*args,**kwargs):

            print('=====================>wrapper2运行了')

            name = input('username>>>:').strip()

            pwd = input('password>>>:').strip()

            if engine == 'file':

              print('基于文件的认证')

              if name == 'egon' and pwd == '123'

                print('login successful')

                res = func(*args,**kwargs)

                return res

              elif engine == 'mysql':

                print('基于mysql的认证')

              elif engine == 'ldap':

                print('基于ldap的认证')

              else:

                print('错误的认证源')

            return wrapper2

          return xxx

      @timmer  #index = timmer(wrapper2的内存地址)  #index = wrapper1的内存地址

      @auth(engine='file')  #@xxx #index = xxx(最原始那个index的内存地址)  #index = wrapper2的内存地址

      def index():

        print('welcome to index page')

        time.sleep(2)

      index()  #wrapper1的内存地址()

  二、迭代器

    1、什么是迭代器

      迭代指的是一个重复的过程,每一次重复都是基于上一次的结果而来的

      li = ['a','b','c','d','e']

      li =('a','b','c','d','e')

      li = 'hello'

      i = 0

      while i < len(li):

        print(li[i])

        i +=1

      迭代器指的是迭代取值的工具,该工具的特点是可以不依赖于索引取值

    2、为何要用迭代器

      为了找出一种通用的&可以不依赖索引的迭代取值方式

    3、如何用迭代器

      可迭代的对象:但凡内置有.__iter__方法的对象都称之为可迭代的对象

      迭代器对象:既内置有__iter__方法,又内置有__next__方法

      关于__iter__方法:

        调用可迭代对象的__iter__会得到一个迭代器对象

        调用迭代器对象的__iter__会得到迭代器本身

    4、总结迭代器的优缺点:

      优点:

      1、提供了一种通用的&可以不依赖索引的迭代取值方式

      2、同一时刻在内存中只有一个值,更加节省内存

      缺点:

      1、取指定值不如索引灵活,并且迭代器是一次性的

      2、无法预知迭代器数据的个数

    可迭代的对象:str,list,tuple,dict,set,文件对象

    迭代器对象:文件对象

    可迭代的对象====》迭代器对象:调用可迭代对象内置的__iter__方法会有一个返回值,该返回值

  就是对应的迭代器对象

    

    dic = {'x':1,'y':2,'z':3}

    iter_dic= dic.__iter__()

    res1 = iter_dic.__next__()

    print(res1)
    res2 = iter_dic.__next__()

    print(res2)

    print(dic.__iter__().__next__())

    print(dic.__iter__().__next__())  #这样定义会重现产生一个可迭代对象,然后会打印x,是错误的~

    迭代器打印文件内容:

      while True:

        try:

          print(iter_dic.__next__())

        except StopIteration:

          break

    for准确地说应该是迭代器循环,for循环的原理如下:

    1、先调用in后面那个值的__iter__方法,得到迭代器对象

    2、执行迭代器.__next__()方法得到一个返回值,然后赋值给一个变量k,运行循环体代码

    3、循环往复,直到迭代器取值完毕抛出异常然后捕捉异常自动结束循环

    dic = {'x':1,'y':2,'z':3}

    iter_dic = dic.__iter__()

    print(iter_dic)

    print(iter_dic.__iter__())

    for k in dic:  #iter_dic=dic.__iter__()

      print(k)

    with open('a.txt',mode='rt',encoding='utf-8') as f:

      for line in f:  #iter_f = f.__iter__()

        print(line)

  三、自定义迭代器

    yield关键字:只能用在函数内

    在函数内但凡包含有yield关键字,再去执行函数,就不会立刻运行函数体代码了

    会得到一个返回值,该返回值称之为生成器对象,生成器本质就是迭代器

    总结yield:

    1、提供一种自定义迭代器的解决方案

    2、yield可用于返回值

      yield VS return

      相同点:都可以用于返回值

      不同点:yield可以暂停函数,yield可以返回多次值,而return只能返回一次值函数就立刻终止

    def func():

      print('=========>第一次')

      yield 1

      print('=========>第二次')

      yield 2

      print('=========>第三次')

      yield 3

      print('=========>第四次')

    g = func()

    #iter(g) = g.__iter__()

    #next(g) = g.__next__()

    res1 = next(g)

    print(res1)

    res2 = next(g)

    print(res2)

    res3 = next(g)

    print(res3)

    res4 = next(g)

    print(res4)

  

  自制一个range函数:

    def my_rage(start,stop,step = 1)

      while start < stop:

        yield start

        start+=step

    res = my_range(1,5,2) 

    next(res)

    next(res) 

    #print(next(res))

    #for item in res:

      #print(item)

    for item in my_range(1,5,2):

      print(item)

  四、xxx生成式

    1、三元生成式

    def max2(x,y):

      if x>y:

        return x

      else:

        return y

    x = 10

    y = 20

    res = '条件成立的值' if x>y else '条件不成立的值'

    print(res)

    2、列表生成式

    l = []

    for i in range(1,11):

      if i > 4:

        res = 'egg%s' %i

        l.append(res)

    print(l)

    l = ['egg%s' %i for i in range(1,11) if i >4]

    print(l)

    names = ['egon','lxx','yyx','cw','alex','wxx']

    l = []

    for name in names:

      if name != 'egon':

        res = '%s_DSB' %name

        l.append(res)

    print(l)

    l = ['%s_DSB' %name for name in names if name !='egon']

    print(l)

    3、生成器表达式

    res = (i**2 for i in range(3))

    print(res)

    print(next(res))

    print(next(res))

    print(next(res))

    print(next(res))  #因为是0-2 所以最多被调用三次 调用第四次的时候会报错

    

    with open('a.txt',mode = 'rt',encoding = 'utf-8') as f:

      data = f.read()

      print(len(data))

    

      res = 0

      for line in f:

        res +=len(line)

      print(res)

      res = sum((len(line) for line in f))

      res = sum(len(line) for line in f)

      print(res)

      res = max([len(line) for line in f])

      res = max((len(line) for line in f))

      res = max(len(line) for line in f)

      print(res)

    4、字典生成式

      items = [('name','egon'),('age',18),('sex','male')]

      dic = {}

      for k,v in items:

        dic[k] = v

      print(dic)

      res = {k:v for k,v in items if k !='sex'}

      print(res)

    5、集合生成式

      res = {i for i in 'hello'}

      print(res)

    

    

原文地址:https://www.cnblogs.com/xiaocaiyang/p/9720610.html