zoukankan      html  css  js  c++  java
  • 迭代器,可迭代对象,生成器

    可迭代对象(iterable),迭代器(iterator),生成器(generator)

     例子

    >>> for key in {'k1':1}:
        print(key)
    
        
    k1
    >>> for i in [1,2,3]:
        print(i)
    
        
    1
    2
    3
    >>> for char in 'chc':
        print(char)
    
    
    
    >>> with open('gy.txt','r') as f:
        for line in f:
            print(line)
    
            
    This is my first text.
    
    This is the first line.
    
    This is the append text

    可迭代对象有__iter__() 方法,迭代器有__iter__() 和__next__() 方法

    对于上面的for 语句,for 语句会对容器对象调用iter()函数,这个函数return一个迭代器对象并且这个对象有__next__方法。每次访问容器对象都会返回一个元素。当后面没元素时,会引发 StopIteration Exception 去告诉for 尊还应该终止了。


    迭代器:(iterator)

    An iterator is an object representing a stream of data; this object returns the data one element at a time.

    A Python iterator must support a method called __next__() that takes no arguments and always returns
    the next element of the stream. If there are no more elements in the stream, __next__() must raise
    the StopIteration exception. Iterators don’t have to be finite, though; it’s perfectly reasonable to write an
    iterator that produces an infinite stream of data.

    迭代器是一个代表一连串数据的对象,这个对象每次返回数据的一个元素。Python 迭代器必须有__call__()方法

    ,这个方法不带参数,总是返回这串数据的下一个数据,当在没有数据会引发StopIteration 异常。

    迭代器不必是有限的,但写一个迭代器让他产生有限的数据是相当合理的。

    迭代器的优点:

    1提供了一种不依赖于索引的取值方式

    2.惰性计算,节省内存

    迭代器的缺点

    1,取值不如按照索引取值方便

    2,一次性的,只能往后走不能往前走

    2无法获得长度

    支持迭代器的数据类型

    python 的序列类型sequence type,字典dictionary,文件对象file(readline),集合set

    迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

    可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)

    for 循环本质就是遵循可迭代协议的访问方式

    先调用object.__iter__()方法,

    dic={0:[1,2,3],1:[4,5,6],2:[7,8,9]}
    x=dic.__iter__()
    x=dic[1].__iter__()
    print(x.__next__())
    print(x.__next__())
    print(x.__next__())

    调用__iter__()方法,就可以转得到迭代器。


    生成器(generator)

    生成器是一个创造迭代器简单且功能强大的工具,可以用常规的函数去写一个生成器,不过这个函数内部要有 yield 语句。

    生成器会自动生成 __iter__ () 和__next__() method ,并且会自动保存程序状态。

    generator expression 

    >>> def f1():
        n=0
        while n<5:
            yield n
            n=n+1
        print('end')
    
        
    >>> f=f1()
    >>> f
    <generator object f1 at 0x000000000316DF68>
    >>> for item in f:
        print(item)
    
        
    0
    1
    2
    3
    4
    end
    >>> hasattr(f,'__iter__')
    True
    >>> hasattr(f,'__next__')
    True
    >>> 

    生成器表达式  generation expression  列表解析 list comprehensions 

    >>> s=(i*i for i in range(5))
    >>> s
    <generator object <genexpr> at 0x000000000316DF10>

     list comprehension 用[] 抱起来   generator expression  用() 

    >>> ls=[i*2 if i>3 else i*i for i in range(6)]
    >>> ls
    [0, 1, 4, 9, 8, 10]
    >>> 

     pass values into a generator

    In Python 2.4 and earlier, generators only produced output. Once a generator’s code was invoked to create
    an iterator, there was no way to pass any new information into the function when its execution is resumed.
    You could hack together this ability by making the generator look at a global variable or by passing in some
    mutable object that callers then modify, but these approaches are messy.
    In Python 2.5 there’s a simple way to pass values into a generator. yield became an expression, returning a
    value that can be assigned to a variable or otherwise operated on:
    val = (yield i)
    I recommend that you always put parentheses around a yield expression when you’re doing something with
    the returned value, as in the above example. The parentheses aren’t always necessary, but it’s easier to
    always add them instead of having to remember when they’re needed.


    (PEP 342 explains the exact rules, which are that a yield-expression must always be parenthesized except
    when it occurs at the top-level expression on the right-hand side of an assignment. This means you can write
    val = yield i but have to use parentheses when there’s an operation, as in val = (yield i) + 12.)
    Values are sent into a generator by calling its send(value) method. This method resumes the generator’s
    code and the yield expression returns the specified value. If the regular __next__() method is called, the
    yield returns None.

    在python 2.4 以及之前,生成器只能产生输出,一旦生成器代码被调用去穿件一个迭代器,当他的执行重新开始时,就没有方式去传递新的信息到函数

    你可以传入一些全局变量,或者通过传入一些可变对象,也能分配给变量, 但是这样会引发混乱。

    在Python2.5以后,有了很简单的方式去传递值到一个生成器中,yield 变成了表达式,返回一个value, 

    val = (yield i)

    当你做一些与返回的数据相关的事情的时候,推荐总是加括号包在这个yield表达式,正如上面的例子,括号不是总需要的,但是很简单的加上它,而不是想起需要加括号再去加上这个括号

    >>> def counter(maxi):
        i=0
        while i< maxi:
            val=(yield i)
            if val is not None:
                i=val
            else:
                i+=1
    
                
    >>> it=counter(10)
    >>> next(it)
    0
    >>> next(it)
    1
    >>> it.send(8)
    8
    >>> next(it)
    9

    生成器函数:函数体内包含yield关键字,该参数执行的结果是生成器函数。生成器本质也是迭代器。

    yield

    1.与return类似,都可以返回值,但不一样的是yield返回多次值,而return只能返回一次值。

    2.为函数封装好__iter__ 和__next__方法,吧函数执行结果做成了迭代器。

    3遵循迭代器的取值方式,next(),触发函数的执行,函数暂停与再继续的状态,都是由yield保存

    三元表达式

    res =  True if 表达式 else False

    View Code

    列表解析式[i for i in range(100) if 表达式]

    生成器表达式(i for i in range(100) if 表达式)

    生成器优点:惰性计算,节省内存

    生成器用途:模拟管道,惰性计算

    面向过程编程:

    import os
    def deco(func):
        def wrapper(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return wrapper
    @deco
    def search_file(target):
        while True:
            path=yield
            g=os.walk(path)#g是生成器
            for i in g:
                for file_name in i[-1]:
                    file_path=r'%s\%s' %(i[0],file_name)
                    target.send(file_path)
    @deco
    def opener(target):
        while True:
            file_path=yield
            with open(file_path,encoding='utf-8') as f:
                target.send((file_path,f))
    
    @deco
    def reader(target):
        while True:
            file_path,f=yield
            for line in f:
                res=target.send((file_path,line))   #grep.send((file_path,line))
                if res:
                    break
    @deco
    def grep(target,word):
        tag = False
        while True:
            file_path, line = yield tag
            tag = False
            if word in line:
                target.send(file_path)
                tag=True
    @deco
    def printer():
        while True:
            file_path = yield
            print(file_path)
    g=search_file(opener(reader(grep(printer(),'root'))))
    g.send(r'E:PYTHON学习excisesday9')
    View Code
  • 相关阅读:
    lua table
    lua basic
    lua5.4 coroutine的通俗理解
    HarmonyOS实战—实现双击事件
    HarmonyOS实战—单击事件的四种写法
    HarmonyOS实战—实现单击事件流程
    苹果CMS对接公众号教程
    Spring快速入门
    YYCMS搭建影视网站教程
    分享几个开源Java写的博客系统
  • 原文地址:https://www.cnblogs.com/yuyang26/p/7019671.html
Copyright © 2011-2022 走看看