Python 3의 구문에서 산출량에 대한 자세한 설명

高洛峰
풀어 주다: 2017-02-21 10:11:00
원래의
1312명이 탐색했습니다.

Python 3.3에서 생성기에는 새로운 구문인 Yield from이 있습니다. Yield from의 기능은 무엇인가요? 구문은 무엇입니까? 다음 글은 Python 3의 구문에서 나오는 Yield 관련 정보를 위주로 자세하게 소개하고 있으니, 필요하신 분들은 참고하시면 좋을 것 같습니다. 잘못된 구문을 직접 보고합니다. 언뜻 보면 2to3 처리에 문제가 있는 줄 알았습니다. 비난할 수는 없습니다. 뭐~ 많은 패키지가 2로 작성되었다가 3으로 변환됩니다. 알고 보니 asyncio만 지원하는 것으로 나타났습니다. 3.3+.버전에서 코드를 다시 보다가 갑자기

라는 문장을 발견했습니다. 그런데 는 마법의 말입니다.

PEP-380pip install asyncioyield fromyield글쎄, 구글을 통해 이 제목을 떠올렸습니다. yield from의 과거와 현재의 삶이 모두 이 PEP에 담겨 있습니다. 일반적인 아이디어는 원래 아이디어입니다

문은 CPU 제어권을 직접 호출자에게만 반환할 수 있습니다. 생성기 또는 코루틴의 Yield 문을 사용하여 논리를 다른 생성기(원래 하위 생성기)로 재구성하려는 경우 매우 유용합니다. 문제가 되는 이유는 외부 생성기가 내부 생성기에 대한 메시지 전달을 담당하기 때문입니다. 그래서 누군가가 프로그래머에게 투명하게 전달하기 위해 Python이 메시지 전달을 캡슐화하도록 하는 아이디어를 갖고 있었기 때문에

이 있었습니다. PEP-380은

의 의미, 즉 중첩된 생성기가 가져야 하는 동작 패턴을 지정합니다.

yield from함수 A에 이러한 명령문이 있다고 가정합니다. yieldyield from

yield from B()
로그인 후 복사

yield from

는 반복 가능한(반복 가능한) 객체 b를 반환한 다음 A() 생성기를 반환합니다. 명명 규칙에 따르면 이름은 a입니다. 그러면

b 반복으로 생성된 각 값은 a의 호출자에게 직접 전달됩니다.

B()

send 메소드를 통해 a에 전송된 모든 값은 b에 직접 전달됩니다. 전송된 값이 None이면 b의
    메소드가 호출되고, 그렇지 않으면 send 메소드가 호출됩니다. b는 이라고 불린다. b에 대한 메서드 호출이 StopIteration 예외를 생성하면 a는
  1. 다음의 문을 계속 실행하고 다른 예외는 a로 전파되어

    을 실행할 때 a에서 예외가 발생하게 됩니다.

  2. a에 GeneratorExit 이외의 예외가 발생하면 해당 예외는 b에 직접 발생합니다. b의 throw 메서드가 StopIteration을 발생시키는 경우 a는 계속해서 실행되고 다른 예외로 인해 a도 예외가 발생하게 됩니다. __next__()yield fromyield from

    a에 GeneratorExit 예외가 발생하거나 a의 닫기 메소드가 호출되고 b에도 닫기 메소드가 있는 경우 b의 닫기 메소드도 호출됩니다. b의 이 메서드에서 예외가 발생하면 a에서도 예외가 발생하게 됩니다. 반대로 b가 성공적으로 닫히면 a도 예외를 발생시키지만 이는 특정 GeneratorExit 예외입니다.
  3. a의
  4. 표현식 평가 결과는 b 반복이 끝날 때 발생하는 StopIteration 예외의 첫 번째 매개변수입니다.
  5. b의
  6. 문은 실제로

    예외를 발생시키므로 b의 return 값은 a의 yield from 식의 반환 값이 됩니다.

  7. return <expr>쉔마는 왜 이렇게 요구사항이 많은가요? throw 메서드를 추가하면 생성기의 동작이 매우 복잡해지기 때문에, 특히 여러 생성기가 함께 있는 경우 이를 작동하려면 프로세스 관리와 유사한 기본 요소가 필요합니다. 위의 모든 요구 사항은 본질적으로 복잡한 생성기 동작을 통합하기 위한 것이므로 당연히 단순화할 수 없습니다. StopIteration(<expr>) yield fromPEP 작성자가 말하려는 내용을 이해하지 못했음을 인정하므로 PEP를 "재구성"하는 것이 도움이 될 수 있습니다.

  8. 쓸데없는 예

아마도 이런 프로그램을 작성하고 싶지 않을 것이기 때문에 쓸모가 없지만... 어쨌든 문제를 설명하기에는 충분합니다. .

다음과 같은 생성기 함수를 상상해 보세요.

def inner():
 coef = 1
 total = 0
 while True:
 try:
  input_val = yield total
  total = total + coef * input_val
 except SwitchSign:
  coef = -(coef)
 except BreakOut:
  return total
로그인 후 복사

이 함수에 의해 생성된 생성기는 send 메서드에서 받은 값을 로컬로 누적합니다. total 변수를 사용하고 BreakOut 예외를 수신하면 반복을 중지합니다. 다른 SwitchSign 예외는 이해하기 어렵지 않으므로 여기서는 스포일러하지 않겠습니다.

코드 관점에서

함수로 얻은 생성기는 send를 통해 작업을 위한 데이터를 수신하는 동시에 throw 메서드를 통해 외부 코드로부터 제어를 받아 다양한 코드 분기를 실행합니다. 지금까지는 매우 명확합니다.

다음으로 요구사항 변경으로 인해

코드 앞뒤에 초기화 및 사이트 정리 코드를 추가해야 합니다. "깨지지 않은 코드는 건들지 말라"는 생각에

를 그대로 두고

를 하나 더 작성하고,

안에 추가된 코드를 넣고, inner()과 동일한 연산을 제공하기로 했습니다. > 인터페이스.

은 생성기의 여러 기능을 활용하므로

는 다음 다섯 가지 작업도 수행해야 합니다. inner()

  1. outer()必须生成一个generator;

  2. 在每一步的迭代中,outer()要帮助inner()返回迭代值;

  3. 在每一步的迭代中,outer()要帮助inner()接收外部发送的数据;

  4. 在每一步的迭代中,outer()要处理inner()接收和抛出所有异常;

  5. outer()被close的时候,inner()也要被正确地close掉。

根据上面的要求,在只有yield的世界里,outer()可能是长这样的:

def outer1():
 print("Before inner(), I do this.")
 i_gen = inner()
 input_val = None
 ret_val = i_gen.send(input_val)
 while True:
 try:
  input_val = yield ret_val
  ret_val = i_gen.send(input_val)
 except StopIteration:
  break
 except Exception as err:
  try:
  ret_val = i_gen.throw(err)
  except StopIteration:
  break
 print("After inner(), I do that.")
로그인 후 복사

WTF,这段代码比inner()本身还要长,而且还没处理close操作。

现在我们来试试外星科技:

def outer2():
 print("Before inner(), I do this.")
 yield from inner()
 print("After inner(), I do that.")
로그인 후 복사

除了完全符合上面的要求外,这四行代码打印出来的时候还能省点纸。

我们可以在outer1()outer2()上分别测试 数据 以及 异常 的传递,不难发现这两个generator的行为基本上是一致的。既然如此, 外星科技当然在大多数情况下是首选。

对generator和coroutine的疑问

从以前接触到Python下的coroutine就觉得它怪怪的,我能看清它们的 行为模式,但是并不明白为什么要使用这种模式,generator和 coroutine具有一样的对外接口,是generator造就了coroutine呢,还 是coroutine造就了generator?最让我百思不得其解的是,Python下 的coroutine将“消息传递”和“调度”这两种操作绑在一个yield 上——即便有了yield from,这个状况还是没变过——我看不出这样做 的必要性。如果一开始就从语法层面将这两种语义分开,并且为 generator和coroutine分别设计一套接口,coroutine的概念大概也会 容易理解一些。

更多Python 3中的yield from语法详解相关文章请关注PHP中文网!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!