질문

파이썬에서 수율 키워드의 사용은 무엇입니까?그것이 무엇을합니까?

예를 들어,이 코드를 이해하려고합니다.

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

그리고 이것은 발신자입니다.

result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

_get_child_candidates 메소드가 호출 될 때 어떻게됩니까? 리턴 된 목록이 반환됩니까?단일 요소?다시 불리는거야?후속 전화가 언제 중지됩니까?


1. This piece of code was written by Jochen Schulz (jrschulz), who made a great Python library for metric spaces. This is the link to the complete source: Module mspace.

답변

 

 

어떤 수율을 이해하기 위해 발전기가 어떤 것을 이해해야합니다.그리고 생성자를 이해하기 전에 iterables를 이해해야합니다.

iterables.

목록을 만들 때 하나씩 항목을 읽을 수 있습니다.하나씩 항목을 읽는 것은 반복이라고합니다.

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

myList는 썩은 것입니다.목록 이해력을 사용할 때 목록을 만들고 iterable :

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

당신이 사용할 수있는 모든 것이 "in ..."on is iserable입니다.목록, 문자열, 파일 ...

이러한 iterables는 원하는만큼 읽을 수 있지만 메모리에 모든 값을 저장할 수 있으므로 모든 값을 많이 저장할 때 원하는 값이 아닙니다.

발전기

발전기는 반복자, 일종의 일종으로 한 번 이상 반복 할 수 있습니다.생성기는 모든 값을 메모리에 저장하지 않으며 즉시 값을 생성합니다.

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

[] 대신에 사용하는 경우는 똑같습니다.그러나 발전기만이 한 번만 사용할 수 있으므로 0을 계산 한 다음 잊어 버리고 1을 계산하고 1을 계산하는 것입니다.

생산하다

수율은 함수가 생성기를 반환하면 반환과 같이 사용되는 키워드입니다.

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

여기에는 쓸모없는 예제이지만, 당신의 기능이 한 번만 읽어야하는 거대한 값 집합을 반환 할 때 편리합니다.

수확량을 마스터하려면 기능을 호출 할 때 기능 본문에 작성한 코드가 실행되지 않음을 이해해야합니다.기능은 Generator 객체 만 반환합니다. 이것은 약간 까다 롭습니다.

그런 다음 코드가 발생할 때마다 꺼져있는 곳에서 코드가 계속 발생합니다.

이제 열심히 :

처음으로 함수에서 생성 된 Generator 객체를 호출하면 함수의 코드를 처음부터 생성 할 때까지 루프의 첫 번째 값을 반환합니다.그런 다음 각 후속 호출은 함수에 작성한 루프의 다른 반복을 실행하고 다음 값을 반환합니다.이것은 생성기가 비어있는 것으로 간주 될 때까지 계속 될 것입니다. 이는 함수가 수확량을 눌러 실행하지 않고 실행될 때 발생합니다.루프가 끝나기 때문에 또는 더 이상 "if / else"를 만족시키지 않기 때문에 일 수 있습니다.


코드 설명

발전기:

# Here you create the method of the node object that will return the generator
def _get_child_candidates(self, distance, min_dist, max_dist):

    # Here is the code that will be called each time you use the generator object:

    # If there is still a child of the node object on its left
    # AND if the distance is ok, return the next child
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild

    # If there is still a child of the node object on its right
    # AND if the distance is ok, return the next child
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild

    # If the function arrives here, the generator will be considered empty
    # there is no more than two values: the left and the right children

방문객:

# Create an empty list and a list with the current object reference
result, candidates = list(), [self]

# Loop on candidates (they contain only one element at the beginning)
while candidates:

    # Get the last candidate and remove it from the list
    node = candidates.pop()

    # Get the distance between obj and the candidate
    distance = node._get_dist(obj)

    # If distance is ok, then you can fill the result
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)

    # Add the children of the candidate in the candidate's list
    # so the loop will keep running until it will have looked
    # at all the children of the children of the children, etc. of the candidate
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result

이 코드에는 몇 가지 스마트 파트가 포함되어 있습니다.

  • The loop iterates on a list, but the list expands while the loop is being iterated. It's a concise way to go through all these nested data even if it's a bit dangerous since you can end up with an infinite loop. In this case, candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) exhaust all the values of the generator, but while keeps creating new generator objects which will produce different values from the previous ones since it's not applied on the same node.

  • The extend() method is a list object method that expects an iterable and adds its values to the list.

보통 우리는 목록을 전달합니다.

>>> a = [1, 2]
>>> b = [3, 4]
>>> a.extend(b)
>>> print(a)
[1, 2, 3, 4]

그러나 귀하의 코드에서는 발전기를 얻습니다.

  1. You don't need to read the values twice.
  2. You may have a lot of children and you don't want them all stored in memory.

메소드의 인수가 목록인지 여부 인 경우 Python이 상관하지 않기 때문에 작동합니다.파이썬은 문자열, 목록, 튜플 및 발전기로 작업 할 수 있도록 iterables를 기대합니다!이것은 오리 타이핑이라고하며 파이썬이 너무 멋지게 이유 중 하나입니다.그러나 이것은 또 다른 이야기입니다.

여기에서 멈출 수 있거나 생성기의 고급 사용을 보려면 조금만 읽을 수 있습니다.

발전기 고갈 제어

>>> 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
...

참고 : Python 3, UsePrint (Corner_Street_Atm .__ Next __ ()) 또는 인쇄 (다음 (다음 (다음 (corner_street_atm))

자원에 대한 액세스를 제어하는 것과 같은 다양한 것들에 유용 할 수 있습니다.

가장 친한 친구

IterTools 모듈에는 iterables를 조작하는 특수 함수가 들어 있습니다.발전기를 복제하고 싶습니까? 체인 두 발전기?하나의 라이너가있는 중첩 된 목록의 그룹 값?다른 목록을 만들지 않고도지도 / zip?

그런 다음 IterTools를 가져 오십시오.

예제?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)]

반복의 내부 메커니즘을 이해합니다

반복은 ITerables (__iter __ () 메소드를 구현) 및 반복자 (__next __ () 메소드를 구현)를 암시하는 프로세스입니다. Iterables는 반복자를 얻을 수있는 모든 개체입니다.Iterators는 iterables에서 반복하는 객체입니다.

루프가 어떻게 작동 하는지이 기사에 대한 더 많은 것이 있습니다.

출처:

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