반복자 발전기 수율, 반복 가능 객체를 알

원본 : https://foofish.net/iterators-vs-generators.html
에서 기사 RQ의 블로그 게시물의 저자는, 원래는 대 반복자 발생기는 대 반복 가능 객체는 , 내가 쓴이 글이 자신의 이해에 따라 이루어집니다 참조 번역, 정말 원래 버전의 번역되지 않습니다, 우리는 원본을 읽어 보시기 바랍니다, 친구 보정 감사합니다.

데이터 구조 파이썬 이해의 컨테이너, 용기, 반복 가능 객체 (의 Iterable), 반복기 (반복자), 발전기 (제너레이터)리스트 / 설정 / 사전 유도 (목록, 설정 딕셔너리 이해) 파라미터의 많은 개념 혼합, 혼란 초보자를위한, 나는이 개념과의 관계 사이의 문서 스트로크 명확한 관계를 사용하려고합니다 불가피하다.

컨테이너 (컨테이너)

컨테이너는 컨테이너 요소를 개별적으로 반복 사용할 수를 취득 할 수 있고, 데이터 요소의 복수의 구조가 그룹화되어있다 in, not in키워드는 요소는 컨테이너에 포함 여부를 판단한다. 이러한 데이터 구조는 일반적으로 모든 요소 파이썬 (예 반복자 발전기 개체로 모든 요소가 메모리에 배치되지 일부 예외로), 공통 컨테이너 객체가 상기 메모리에 저장된 :

  • 목록 및 ....
  • ,, frozensets을 설정 ....
  • DICT, defaultdict, OrderedDict, 카운터, ...
  • 튜플, namedtuple, ...
  • STR

당신은 아무것도를 연결 할 수있는 상자, 집, 찬장,으로 볼 수 있기 때문에 쉽게 컨테이너, 이해합니다. 이 요소가 내부에 포함되어 있는지 여부를 문의하는 데 사용할 수있는 뷰의 기술적 인 관점에서, 오브젝트는 컨테이너, 예컨대리스트로서 설정 튜플 컨테이너 객체되어 고려 될 수있다 :

>>> assert 1 in [1, 2, 3]      # lists
>>> assert 4 not in [1, 2, 3]
>>> assert 1 in {1, 2, 3}      # sets
>>> assert 4 not in {1, 2, 3}
>>> assert 1 in (1, 2, 3)      # tuples
>>> assert 4 not in (1, 2, 3)

키 DICT DICT에 사용되는 요소 여부를 묻는 :

>>> d = {1: 'foo', 2: 'bar', 3: 'qux'}
>>> assert 1 in d
>>> assert 'foo' not in d  # 'foo' 不是dict中的元素

문자열에서 문자열 여부를 묻습니다 :

>>> s = 'foobar'
>>> assert 'b' in s
>>> assert 'x' not in s
>>> assert 'foo' in s 

용기의 대부분이 요소의 모든 하나를 얻을 수있는 방법을 제공하지만이 기능은 용기 자체에서 제공하지만,하지 않지만 반복자는 이 능력의 컨테이너를 주어진 물론, 모든 컨테이너를 사용할 수 있습니다하지 같은 반복 : 블 필터 , 블룸 필터 요소가 그들 각각의 값을 획득 컨테이너에 포함 아니라 용기로부터 여부 블룸 필터 용기에 저장 근본적으로 어떠한 요소 없다로서 검출하는데 사용될 수 있지만, 그러나이 해시 함수에 의해 배열에 저장된 값에 매핑된다.

반복 가능 객체 (반복 가능)

그냥 많은 용기는 더 많은 개체에 추가하여, 반복 가능 객체이며, 또한 반복 가능한, 등등 열려있는 파일, 소켓, 그리고 상태에서있는 그대로 말했다. 그러나 반환 할 수있는 사람 반복자 조금 혼란 들리 겠지만, 반복 가능 객체 호출 할 수있는 객체, 그것은 예를 들어 보면, 문제가되지 않습니다 :

>>> x = [1, 2, 3]
>>> y = iter(x)
>>> z = iter(x)
>>> next(y)
1
>>> next(y)
2
>>> next(z)
1
>>> type(x)
<class 'list'>
>>> type(y)
<class 'list_iterator'>

여기에서 x, 목록 객체를 어떤 특정 데이터 유형을 참조하지 않고, 반복자 객체 컨테이너이고 반복 가능 객체가 동일들에게 인기있는 이름이 반복된다, 딕셔너리는 반복 가능 객체이고, SET는 반복 가능 객체이다. y그리고 z두 개의 별도의 반복자 오른쪽 요소를 얻기 위해 다음 반복 편리한 시간에 현재 반복의 위치를 기록하는 데 사용 된 상태 내에서 유지 반복자. 반복자는, 예를 들어 특정 반복자 타입을 가지고 있습니다 list_iterator, set_iterator. 반복 가능 객체는 달성 __iter__반복자 객체를 반환 방법을.

당신은 코드를 실행하면 :

x = [1, 2, 3]
for elem in x:
    ...

실제 구현은 다음과 같습니다

코드의 섹션을 디 컴파일, 당신은 명시 적으로 호출 할 인터프리터를 볼 수있는 GET_ITER호출에 해당하는, 명령 iter(x), FOR_ITER지시는 호출하는 것입니다 next(), 방법을 반복자의 다음 요소를 얻기 위해 계속하지만, 명령에서 직접에서 볼 수없는 그 때문에 전에 통역을 최적화.

>>> import dis
>>> x = [1, 2, 3]
>>> dis.dis('for _ in x: pass')
  1           0 SETUP_LOOP              14 (to 17)
              3 LOAD_NAME                0 (x)
              6 GET_ITER
        >>    7 FOR_ITER                 6 (to 16)
             10 STORE_NAME               1 (_)
             13 JUMP_ABSOLUTE            7
        >>   16 POP_BLOCK
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE

반복자 (반복자)

那么什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter____next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常,至于它们到底是如何实现的这并不重要。

所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。有很多关于迭代器的例子,比如itertools函数返回的都是迭代器对象。

生成无限序列:

>>> from itertools import count
>>> counter = count(start=13)
>>> next(counter)
13
>>> next(counter)
14

从一个有限序列中生成无限序列:

>>> from itertools import cycle
>>> colors = cycle(['red', 'white', 'blue'])
>>> next(colors)
'red'
>>> next(colors)
'white'
>>> next(colors)
'blue'
>>> next(colors)
'red'

从无限的序列中生成有限序列:

>>> from itertools import islice
>>> colors = cycle(['red', 'white', 'blue'])  # infinite
>>> limited = islice(colors, 0, 4)            # finite
>>> for x in limited:                         
...     print(x)
red
white
blue
red

为了更直观地感受迭代器内部的执行过程,我们自定义一个迭代器,以斐波那契数列为例:

class Fib:
    def __init__(self):
        self.prev = 0
        self.curr = 1

    def __iter__(self):
        return self

    def __next__(self):
        value = self.curr
        self.curr += self.prev
        self.prev = value
        return value

>>> f = Fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了__next__方法)。实例变量prevcurr用户维护迭代器内部的状态。每次调用next()方法的时候做两件事:

  1. 为下一次调用next()方法修改状态
  2. 为当前这次调用生成返回结果

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

生成器(generator)

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:

def fib():
    prev, curr = 0, 1
    while True:
        yield curr
        prev, curr = curr, curr + prev

>>> f = fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

fib就是一个普通的python函数,它特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。

生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似:

def something():
    result = []
    for ... in ...:
        result.append(x)
    return result

都可以用生成器函数来替换:

def iter_something():
    for ... in ...:
        yield x

生成器表达式(generator expression)

生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。

>>> a = (x*x for x in range(10))
>>> a
<generator object <genexpr> at 0x401f08>
>>> sum(a)
285

总结

  • 容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
  • 可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
  • 迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next____iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
  • 生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield

参考链接:https://docs.python.org/2/library/stdtypes.html#iterator-types



MARSGGBO原创





2019-7-17



추천

출처www.cnblogs.com/marsggbo/p/11203768.html