迭代器、生成器和装饰器

迭代器iterator

  • 迭代器是一个可以记住遍历的位置的对象

  • 迭代器只能往前不能后退

  • 迭代器有两个基本方法

    • iter()创建迭代器对象
    • next()输出迭代器的下一个元素
  • 字符串,列表或元组对象都可用于创建迭代器

  • l = [1, 2, 3, 4]
    l_iter = l.__iter__()
    while True:
        try:
            # item = l_iter.__next__()
            # print(item)
            print(next(l_iter))
        except StopIteration:
            break
    
    #判断range()中是否有__iter__方法和__next__方法,是否是迭代器
    print("__iter__" in dir(range(12)))
    print("__next__" in dir(range(12)))
    print(isinstance(range(100000000), Iterator))
    #1
    #2
    #3
    #4
    #True
    #False
    #False
    
    class MyNumbers:
      def __iter__(self):
        self.a = 1
        return self
      def __next__(self):
        if self.a <= 20:
          x = self.a
          self.a += 1
          return x
        else:
          raise StopIteration
    myclass = MyNumbers()
    myiter = iter(myclass)
    for x in myiter:
      print(x)
    

生成器generator

  • 是一个特殊的迭代器

  • 使用了yield的函数,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值,在下一次执行next()方法时从当前位置继续运行。

  • 返回迭代器对象

  • 使用生成器实现斐波那契数列

    import sys 
    def fibonacci(n): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            yield a
            a, b = b, a + b
            counter += 1
    f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
    while True:
        try:
            print (next(f), end=" ")
        except StopIteration:
            sys.exit()
    
  • yield from

    def gen1():
        for c in 'AB':
            yield c
        for i in range(3):
            yield i
    print(list(gen1()))
    #['A', 'B', 0, 1, 2]
    
  • send

    # send 获取下一个值的效果和next基本一致
    # 只是在获取下一个值的时候,给上一yield的位置传递一个数据
    # 使用send的注意事项
    ## 第一次使用生成器的时候 是用next获取下一个值
    ## 最后一个yield不能接受外部的值
    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        yield 2
    
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   #send的效果和next一样
    print('***',ret)
    #123
    #*** 1
    #======= hello
    #456
    #*** 2
    # #计算移动平均值
    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    
    g_avg = averager()
    next(g_avg)
    print(g_avg.send(10))
    print(g_avg.send(30))
    print(g_avg.send(5))
    #10.0
    #20.0
    #15.0
    
  • 生成器表达式

    laomuji=('鸡蛋%s' %i for i in range(10))
    print(laomuji)
    print(next(laomuji)) #next本质就是调用__next__
    print(laomuji.__next__())
    print(next(laomuji))
    #生成器表达式的应用
    print(sum(x ** 2 for x in range(4)))
    #<generator object <genexpr> at 0x00EAD290>
    #鸡蛋0
    #鸡蛋1
    #鸡蛋2
    #14
    #生成器几乎不占用内存
    

装饰器decorator

  • 基本装饰器

    import time
    from functools import wraps
    
    def timethis(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            re = func(*args, **kwargs)
            end = time.time()
            print(func.__name__, end-start)
            return re
        return wrapper
    @timethis
    def count(n):
        while n > 0:
            n -= 1
    count(30000)
    #count 0.009998083114624023
    
  • 可以自主增删的装饰器

    import time
    from functools import wraps
    
    def outer(flag):
        def timethis(func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                if flag:
                    start = time.time()
                    re = func(*args, **kwargs)
                    end = time.time()
                    print(func.__name__, end - start)
                    return re
                else:
                    return func(*args, **kwargs)
            return wrapper
        return timethis
    
    @outer(True)
    #@outer(False)
    def count(n):
        while n > 0:
            n -= 1
        print("over")
    count(30000)
    #over
    #count 0.020034313201904297
    
    
  • 多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')
    f()
    #wrapper2 ,before func
    #wrapper1 ,before func
    #in f
    #wrapper1 ,after func
    #wrapper2 ,after func
    
  • class Test(object):
    
        def __init__(self, func):
            print('test init')
            print('func name is %s ' % func.__name__)
            self.__func = func
    
        def __call__(self, *args, **kwargs):
            print('装饰器中的功能')
            self.__func()
    @Test
    def test():
        print('this is test func')
    test()
    #test init
    #func name is test 
    #装饰器中的功能
    #this is test func
    
    
posted @ 2020-09-01 02:40  guguda  阅读(87)  评论(0)    收藏  举报