Python generators mainly use Yield. A generator function is defined like a normal function, whenever it needs to generate a value, it is done by using the yield keyword rather than return. When yield keyword is in the body of a def, the function automatically becomes a generator function.
With reference to the code, candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) exhausts all values of the generator and while keeps on generating new generator objects which produce different values every time as it is not applied on the same node. The function gets_child_candidates acts as an iterator and it adds one element at a time to the new list when you extend the list.
Also, in your code, a generator is passed as an argument to extend() method even though it is a list object method. Since Python expects iterables so it works with everything even with generators.