파이썬 'yield' 커맨드

LONGNEW·2020년 12월 23일
0

StackOverFlaw

목록 보기
1/16

https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do

Q. What is the use of the yield keyword in Python, and what does it do?
Q. 파이썬에서 yield 키워드의 쓰임새와 사용방법은 어떻게 되나요?


To understand what yield does, you must understand what generators are.
yield가 동작하는 것을 이해하기 전에, generator가 무엇인지 알아야 합니다.
And before you can understand generator, you must understand iterables.
그리고 generator를 이해하기 전에, iterable을 이해해야 합니다.

Iterables

When you create a list, you can read its items one by one.
list를 생성할 때, 사용자는 리스트의 요소를 하나씩 확인할 수 있습니다.

Reading its items one by one is called iteration:
iteration을 이용해서 리스트의 요소를 읽는 방법:

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

mylist is an iterable.
mylist는 iterable(반복이 가능한 객체)하다.
When you use a list comprehension, you create a list, and so an iterable:
list comprehension을 사용해서 만든 리스트도, iterable 하다.

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

Everything you can use "for... in..." on is an iterable; lists, strings, files...
사용자가 반복문을 이용할 수 있는 객체들은 다 iterable하다고 한다.
These iterables are handy because you can read them as much as you wish, but you store all the values in memory and this is not always what you want when you have a lot of values.
이러한 iterable들은 매우 편리하다. 사용자가 원하는 만큼 요소들을 확인 할수 있기 때문이다.
그러나 메모리 안에 모든 값들을 저장해두는 것은 사용자가 원하는 방식이 아닐 수 있다.

Generators

Generators are iterators, a kind of iterable you can only iterate over once.
Generator는 iterator의 한 종류인데, 단 한 번만 반복을 할수 있는 객체이다.
Generators do not store all the values in memory, they generate the values on the fly:
Generator은 모든 값을 메모리에 저장하지 않고, 그때그때 다른 값들을 생성하는 것.

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

It is just the same except you used () instead of [].
()을 쓴다는 것이 유일한 차이점이다.
BUT, you cannot perform for i in mygenerator a second time since generators can only be used once:
generator의 반복은 한 번만 할 수 있기 때문에. for문을 여러 번 수행 할 수 없다.
they calculate 0, then forget about it and calculate 1, and end calculating 4, one by one.
generator는 0을 찾은 후 리턴 한 다음에 잊어버림, 그 다음 1, 4 순서대로 하나씩 반복 된다.

Yield

yield is a keyword that is used like return, except the function will return a generator.
yieldreturn 처럼 행동한다.(generator를 리턴 하는 경우를 제외 하고)

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

Here it's a useless example, but it's handy when you know your function will return a huge set of values that you will only need to read once.
의미없는 예시 긴한데, 만약 한 번만 순환 할 거대한 리스트를 리턴해야 하는 함수를 만들 때 이와 같은 방법은 매우 유용합니다.
To master yield, you must understand that when you call the function, the code you have written in the function body does not run.
yield를 제대로 이해 하기위해선, 사용자가 이해해야 할 것은 메소드를 호출 했을 때, 사용자가 작성한 코드들이 실행되지 않는다는 것을 알아야 합니다.
The function only returns the generator object, this is a bit tricky 😂
메소드는 오로지 generator 객체만을 리턴 합니다.
Then, your code will continue from where it left off each time for uses the generator.
실행 되지 않던 코드는 for가 실행되고 generator를 이용 할 때마다, 이전의 실행 되지 않았던 부분부터.

Now the hard part:
인제, 어려운 파트
The first time the for calls the generator object created from your function, it will run the code in your function from the beginning until it hits yield, then it'll return the first value of the loop.
처음 for문으로 메소드에서 만들어진 generator객체를 호출 할 때, 메소드의 코드는 시작부터 yield를 만나기 전까지 작동한 후 루프의 첫 번째 값을 리턴 합니다.
Then, each subsequent call will run another iteration of the loop you have written in the function and return the next value.
그리고, 반복문의 호출이 이어질 때 마다 그 다음 값들이 리턴 됩니다.
This will continue until the generator is considered empty, which happens when the function runs without hitting yield.
메소드가 작동할 때 더이상 yield를 만나지 못하면 generator가 빈 것으로 여깁니다.
That can be because the loop has come to an end, or because you no longer satisfy an "if/else".
"if/else" 조건을 만족 하지 못하거나, 반복이 끝 까지 행해 졌기 때문입니다.


You can stop here, or read a little bit to see an advanced use of a generator:

Controlling a generator exhaustion

>>> class Bank(): # Let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self):
...        while not self.crisis:
...            yield "$100"
>>> hsbc = Bank() # When everything's ok the ATM gives you as much as you want
>>> corner_street_atm = hsbc.create_atm()
>>> print(corner_street_atm.next())
$100
>>> print(corner_street_atm.next())
$100
>>> print([corner_street_atm.next() for cash in range(5)])
['$100', '$100', '$100', '$100', '$100']
>>> hsbc.crisis = True # Crisis is coming, no more money!
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # It's even true for new ATMs
>>> print(wall_street_atm.next())
<type 'exceptions.StopIteration'>
>>> hsbc.crisis = False # The trouble is, even post-crisis the ATM remains empty
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> brand_new_atm = hsbc.create_atm() # Build a new one to get back in business
>>> for cash in brand_new_atm:
...    print cash
$100
$100
$100
$100
$100
$100
$100
$100
$100
...

Note: For Python 3, use print(corner_street_atm.next()) or print(next(corner_street_atm))

It can be useful for various things like controlling access to a resource.
리소스에 대한 접근을 제안하는 다양한 경우에 유용하게 쓸 수 있습니다.

Itertools, your best friend

The itertools module contains special functions to manipulate iterables.
itertool 모듈은 iterable을 다루기 위해 다양한 기능들을 가지고 있습니다.
Ever wish to duplicate a generator? Chain two generators? Group values in a nested list with a one-liner? Map / Zip without creating another list?
generator의 복사, generator 합치기, 중첩 리스트에 있는 값 한 줄로 합치기, 다른 리스트를 생성 하지 않고 Map / Zip을 사용하려 할 때가 있나요???
Then just import itertools.
그러면 그냥 itertoolsimport하면 됩니다.

An example? Let's see the possible orders of arrival for a four-horse race:
예를 들어, 4개의 경주마들의 도착순서로 가능한 모든 경우의 수를 확인해 봅시다.

>>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
 (1, 2, 4, 3),
 (1, 3, 2, 4),
 (1, 3, 4, 2),
 (1, 4, 2, 3),
 (1, 4, 3, 2),
 (2, 1, 3, 4),
 (2, 1, 4, 3),
 (2, 3, 1, 4),
 (2, 3, 4, 1),
 (2, 4, 1, 3),
 (2, 4, 3, 1),
 (3, 1, 2, 4),
 (3, 1, 4, 2),
 (3, 2, 1, 4),
 (3, 2, 4, 1),
 (3, 4, 1, 2),
 (3, 4, 2, 1),
 (4, 1, 2, 3),
 (4, 1, 3, 2),
 (4, 2, 1, 3),
 (4, 2, 3, 1),
 (4, 3, 1, 2),
 (4, 3, 2, 1)]

Understanding the inner mechanisms of iteration

Iteration is a process implying iterables (implementing the iter() method) and iterators (implementing the next() method).
순환(Iteration)은 iterable(iter()메소드를 실행)과 iterator(next() 메소드를 실행)를 이용해서 진행된다.
Iterables are any objects you can get an iterator from.
iterable은 iterator를 가져올 수 있는 모든 객체를 뜻한다.
Iterators are objects that let you iterate on iterables.
iterator은 iterable들을 반복할 수 있게 해주는 객체이다.


on the fly : 그때그때 봐 가며
concise : ad, 간결한, 축약된
handy : ad 유용한, 편리한
one by one : 하나하나씩
subsequent : ad 연속적인, (그)다음의

0개의 댓글