파이썬 반복 종이, 반복자 및 발전기의 개념을 알 수 있습니다

정보
프로그램 원숭이 사려 깊은, 평생 학습 실무자, 신생 팀에서 현재 어떤 팀의 리더이며, 기술 스택은 안드로이드, 파이썬, 자바, Go를 포함, 이것은 주요 기술이 우리 팀을 스택입니다.
GitHub의 : https://github.com/hylinux1024
마이크로 채널 대중 번호 : 평생 개발자 (angrycode)

에서 Python반복 가능한 ( Iterable), 반복자 ( Iterator)와 발전기 ( Generator) 이러한 개념은 종종 사용되며, 이러한 몇 초보자가 알아 내기 위해 몇 가지 개념을 넣어 시간, 개념과 자주 혼동이다.

× 00의 반복 가능한 (의 Iterable)

단순히 긴 실현의 실현 한, (파이썬에서 모든 것은 객체) 객체를 넣어 __iter__()하는 방법, 다음 isinstance()검사의 함수 Iterable객체;

예를 들면

class IterObj:
    
    def __iter__(self):
        # 这里简单地返回自身
        # 但实际情况可能不会这么写
        # 而是通过内置的可迭代对象来实现
        # 下文的列子中将会展示
        return self 

클래스의 상기 정의 IterObj및 구현은 __iter__()이것이이다 방법을 반복 할 (의 Iterable) 개체

    it = IterObj()
    print(isinstance(it, Iterable))  # true
    print(isinstance(it, Iterator))  # false
    print(isinstance(it, Generator)) # false

이 클래스를 기억, 우리는이 클래스 정의 아래에 표시됩니다.

일반적인 반복 가능 객체

Python공통되는 반복자는가?

  1. 설정 순서 또는 유형 (예를 들어 list, tuple, set, dict, str)
  2. File 객체
  3. 클래스의 정의 __iter__()방법 개체로서 고려 될 수 Iterable있는 개체하지만 반복적 사용자 객체가 할 수 있도록 for정확한주기를 사용하여, 상기 확인하는 것이 필요하다 __iter__()구현 즉, 내장하여 (정확해야 iter()하는 기능 설정 Iterator객체. 대하여 Iterator이하 설명은 기억, 구덩이를 떠나 여기에있을 것입니다 iter()함수가 다음에하는 반복 가능한 반복자 객체로 전환 할 수있는 기능입니다 for) 사용
  4. 단지 클래스에서 구현되는 경우 달성 __getitem__()개체 수 iter()자체가 반복의 객체를 반복자 함수로 변환하지만. 그래서 객체가 할 수있을 때 for사이클에서 실행하지만, 필요하지 Iterable객체.

1,2 점은 우리는 다음을 확인할 수 있습니다

    print(isinstance([], Iterable))  # true list 是可迭代的
    print(isinstance({}, Iterable))  # true 字典是可迭代的
    print(isinstance((), Iterable))  # true 元组是可迭代的
    print(isinstance(set(), Iterable))  # true set是可迭代的
    print(isinstance('', Iterable))  # true 字符串是可迭代的
    
    currPath = os.path.dirname(os.path.abspath(__file__))
    with open(currPath+'/model.py') as file:
        print(isinstance(file, Iterable)) # true

우리는 볼 점 3 ,

    print(hasattr([], "__iter__")) # true
    print(hasattr({}, "__iter__")) # true
    print(hasattr((), "__iter__")) # true
    print(hasattr('', "__iter__")) # true

이 내장 된 세트 또는 시퀀스 오브젝트가 __iter__그들이 방법으로 같은 이름을 달성 한 속성을. 그러나이 반복 가능 객체가 할 for다음은 내장해야한다, 사용주기에있을 iter()함수 호출 및 변환 Iterator객체.
예를 들어, 우리는 내장 된 반복 가능 객체보고

    print(iter([])) # <list_iterator object at 0x110243f28>
    print(iter({})) # <dict_keyiterator object at 0x110234408>
    print(iter(())) # <tuple_iterator object at 0x110243f28>
    print(iter('')) # <str_iterator object at 0x110243f28>

이들은 각각 해당 반복기 (로 전환된다 Iterator) 개체.
이제 돌아가서의 정의의 시작 부분에 보면 IterObj클래스

class IterObj:
    
    def __iter__(self):
        return self 
        
it = IterObj()
print(iter(it))

우리는 사용 iter()기능, 다음과 같은 정보가 밖으로이 시간 Jiangzai 콘솔 인쇄 :

Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/iterable_iterator_generator.py", line 71, in <module>
    print(iter(it))
TypeError: iter() returned non-iterator of type 'IterObj'

오류의 유형을 의미 발생 iter()함수 반복자 타입으로 '비 반복기를'전송 될 수 없다.

그럼 어떻게 하나의 반복 (수 있습니다 Iterable반복자 (로) 객체 Iterator) 객체?
우리는 수정거야 IterObj클래스의 정의를

class IterObj:

    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]

    def __iter__(self):
        return iter(self.a)

우리는에라는 이름의 생성자 정의 a목록을, 또한 구현하는 __iter__()방법을.

수정 된 클래스 수 iter()즉 될 수 함수를 호출 for사용주기

    it = IterObj()
    print(isinstance(it, Iterable)) # true
    print(isinstance(it, Iterator)) # false
    print(isinstance(it, Generator)) # false
    print(iter(it)) # <list_iterator object at 0x102007278>
    for i in it:
        print(i) # 将打印3、5、7、11、13、17、19元素

따라서 반복자 오브젝트를 정의 할 때, 우리는에주의 __iter__()개체 (예를 들면, 상기 한 세트의 시퀀스, 또는 다른 파일을 정확하게 정의 될 수있다 다수의 반복으로 알려져 있으며, 일반적으로 구현되는 내부 프로세스 로직 반복 가능한) 달성하기 위해 우리를 지원하기 위해

소개 포인트 (4)는 상술 한 것을 의미 iter()기능이 달성 될 수 __getitem__()있을 수있어서 반복자 객체로 변환 대상 for사용주기하지만 만약 isinstance()시간 검출 방법,이 반복자 객체 아니다.

class IterObj:
    
    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]
    
    def __getitem__(self, i):
        return self.a[i]
        
it = IterObj()
print(isinstance(it, Iterable)) # false
print(isinstance(it, Iterator)) # false
print(isinstance(it, Generator)) false
print(hasattr(it, "__iter__")) # false
print(iter(it)) # <iterator object at 0x10b231278>

for i in it:
    print(i) # 将打印出3、5、7、11、13、17、19

이 예는 캔 설명 에서 for사용되는 객체, 그것은 반드시 반복 가능 객체가 아닙니다.

이제 우리는 요약합니다

  1. 반복 된 목적은 달성하는 __iter__()오브젝트의 메소드
  2. 그것은 될 것입니다 for그것은 충족해야 사용 사이클 iter()호출 (즉, 잘못되지 않습니다이 함수를 호출, 적절한로 설정할 수 있습니다 Iterator오브젝트)
  3. 반복 가능 객체를 반복 가능한 알려져 우리의 사용자 정의를 달성하기 위해 도움을받을 수 있습니다.
  4. 개체는 구현 __getitem__()방법이 될 수 iter()함수로 변환 Iterator될 수있는 for루프에서 사용하지만 반복자 객체 아니다 (isinstance 가능한 검출법 ())

반복자하는 0x01 (반복자)

많은 장소는 위에서 언급 한 Iterator지금 우리는 구덩이를 다 채우실 필요.
우리는 반복자에 대한 반복의 개념을 이해하면 더 나은 이해된다.
객체 구현 __iter__()__next__()방법, 그것은 반복자 객체이다. 예를 들면

class IterObj:

    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]

        self.n = len(self.a)
        self.i = 0

    def __iter__(self):
        return iter(self.a)

    def __next__(self):
        while self.i < self.n:
            v = self.a[self.i]
            self.i += 1
            return v
        else:
            self.i = 0
            raise StopIteration()

에서 IterObj목록, 생성자의 정의 a,리스트의 길이 n, 인덱스 i.

    it = IterObj()
    print(isinstance(it, Iterable)) # true
    print(isinstance(it, Iterator)) # true
    print(isinstance(it, Generator)) # false
    print(hasattr(it, "__iter__")) # true
    print(hasattr(it, "__next__")) # true

우리는 상기 찾을 수 있습니다
컬렉션과 객체가 반복 순서가 아니라 반복자입니다

    print(isinstance([], Iterator)) # false
    print(isinstance({}, Iterator)) # false
    print(isinstance((), Iterator)) # false
    print(isinstance(set(), Iterator)) # false
    print(isinstance('', Iterator)) # false

파일 객체는 반복자입니다

    currPath = os.path.dirname(os.path.abspath(__file__))
    with open(currPath+'/model.py') as file:
        print(isinstance(file, Iterator)) # true

반복자 ( Iterator) 객체는 수뿐만 아니라 for주기, 내장의 기능도 할 수 있습니다 사용하는 next()호출 기능. 예를 들면

it = IterObj()
next(it) # 3
next(it) # 5

0x02의 발전기 (제너레이터)

이제 빌더 무엇인지 살펴 보자?
발전기는 모두 반복적 인 반복자

생성기는 두 가지 방법을 정의한다 :

  1. 목록 작성기
  2. 하여 yield함수 발생기의 정의

사례 1 봐

    g = (x * 2 for x in range(10)) # 0~18的偶数生成器 
    print(isinstance(g, Iterable)) # true
    print(isinstance(g, Iterator)) # true
    print(isinstance(g, Generator)) # true
    print(hasattr(g, "__iter__")) # true
    print(hasattr(g, "__next__")) # true
    print(next(g)) # 0
    print(next(g)) # 2

데이터를 필요로 할 때 목록 작성기에만 계산됩니다 거대한 목록을 생성하기 위해 많은 메모리를 소비 할 필요가 있습니다.
사례 2 봐

def gen():
    for i in range(10):
        yield i 

yield효과는 동일하다 return,이 함수의 차수가 반환 [0,10)자연수로 제조 할 수 next()또는 for반복 루프.
프로그램이 발견 한 경우 yield키워드를 다시 한 번 수행 할 때까지, 발전기 함수가 리턴, next()기능, 그것은 즉, 마지막 실행 점 함수가 반환에서 계속 yield기능 실행의 위치에 정보를 저장, 변수 등 출구에, 이것에 다시 실행될 때 yield출구 장소를 계속합니다.
에서 Python발전기의 이러한 기능을 활용하여 코 루틴 구현 될 수있다. 코 루틴 높은 동시성 시나리오의 처리에 대하여 그 스레드, 스레드 경량으로 이해 많은 장점이 될 수있다.

여기에 실현 코 루틴의 표정으로 생산자 - 소비자 모델

def producer(c):
    n = 0
    while n < 5:
        n += 1
        print('producer {}'.format(n))
        r = c.send(n)
        print('consumer return {}'.format(r))


def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('consumer {} '.format(n))
        r = 'ok'


if __name__ == '__main__':
    c = consumer()
    next(c)  # 启动consumer
    producer(c)

이 코드는 다음과 같은 효과를 수행

producer 1
consumer 1 
producer return ok
producer 2
consumer 2 
producer return ok
producer 3
consumer 3 
producer return ok

코 루틴 달성 CPU동시성을 달성하기 위해 두 가지 기능의 전환 효과.

를 0x04 견적

  1. https://docs.python.org/3.7/

추천

출처www.cnblogs.com/angrycode/p/11386970.html