标签云

微信群

扫码加入我们

WeChat QR Code

What is the use of the yield keyword in Python? What does it do?For example, I'm trying to understand this code1:def _get_child_candidates(self, distance, min_dist, max_dist):if self._leftchild and distance - max_dist < self._median:yield self._leftchildif self._rightchild and distance + max_dist >= self._median:yield self._rightchildAnd this is the caller: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 resultWhat happens when the method _get_child_candidates is called?Is a list returned? A single element? Is it called again? When will subsequent calls stop?1. The code comes from Jochen Schulz (jrschulz), who made a great Python library for metric spaces. This is the link to the complete source: Module mspace.


All iterators can only be iterated over once, not just those produced by generator functions.If you don't believe me, call iter() on any iterable object and try to iterate over the result more than once.

2019年04月25日58分02秒

Craicerjack You have your terms mixed up.An iterable is something with an __iter__ method.An iterator is the result of calling iter() on an iterable.Iterators can only be iterated over once.

2019年04月25日58分02秒

yield is not as magical this answer suggests. When you call a function that contains a yield statement anywhere, you get a generator object, but no code runs. Then each time you extract an object from the generator, Python executes code in the function until it comes to a yield statement, then pauses and delivers the object. When you extract another object, Python resumes just after the yield and continues until it reaches another yield (often the same one, but one iteration later). This continues until the function runs off the end, at which point the generator is deemed exhausted.

2019年04月25日58分02秒

MatthiasFripp has pointed out exactly what made me stumble reading this answer."your code will be run each time" is a misleading statement."Your code will continue from where it left off" is a more accurate way to phrase it.

2019年04月25日58分02秒

"These iterables are handy... but you store all the values in memory and this is not always what you want", is either wrong or confusing. An iterable returns an iterator upon calling the iter() on the iterable, and an iterator doesn't always have to store its values in memory, depending on the implementation of the iter method, it can also generate values in the sequence on demand.

2019年04月25日58分02秒

"When you see a function with yield statements, apply this easy trick to understand what will happen" Doesn't this completely ignore the fact that you can send into a generator, which is a huge part of the point of generators?

2019年04月25日58分02秒

"it could be a for loop, but it could also be code like otherlist.extend(mylist)" -> This is incorrect. extend() modifies the list in-place and does not return an iterable. Trying to loop over otherlist.extend(mylist) will fail with a TypeError because extend() implicitly returns None, and you can't loop over None.

2019年04月25日58分02秒

pedro You have misunderstood that sentence. It means that python performs the two mentioned steps on mylist (not on otherlist) when executing otherlist.extend(mylist).

2019年04月25日58分02秒

__getitem__ could be defined instead of __iter__. For example: class it: pass; it.__getitem__ = lambda self, i: i*10 if i < 10 else [][0]; for i in it(): print(i), It will print: 0, 10, 20, ..., 90

2019年04月25日58分02秒

I tried this example in Python 3.6 and if I create iterator = some_function(), the variable iterator does not have a function called next() anymore, but only a __next__() function. Thought I'd mention it.

2019年04月25日58分02秒

This is close, but not correct.Every time you call a function with a yield statement in it, it returns a brand new generator object.It's only when you call that generator's .next() method that execution resumes after the last yield.

2019年04月25日58分02秒

"build me a sequence of stuff" - I'd say an iterable rather than a sequence

2019年04月25日58分02秒

arekolek It bugged me too that I didn't use the words iterator or iterable anywhere. Fixed that, and linked to a good iterable/iterator explainer. But I wanted to keep that initial one-line-version-of-the-whole-answer to a conceptual level. So I deliberately avoided using reserved words there. Because jumping to a glossary is I believe what makes the accepted answer take so long to get to the aha moment. I think the before/after code comparison does that much more quickly.

2019年04月25日58分02秒

Finally got your point, arekolek, that sequence has a specific meaning in Python. Changed to series.

2019年04月25日58分02秒

Just a note - in Python 3, range also returns a generator instead of a list, so you'd also see a similar idea, except that __repr__/__str__ are overridden to show a nicer result, in this case range(1, 10, 2).

2019年04月25日58分02秒

Cute! A trampoline (in the Lisp sense). Not often one sees those!

2019年04月25日58分02秒

This is understandable, but one major difference is that you can have multiple yields in a function/method. The analogy totally breaks down at that point. Yield remembers its place in a function, so the next time you call next(), your function continues on to the next yield. This is important, I think, and should be expressed.

2019年04月25日58分02秒

Don't forget that 2 is prime :-)

2019年04月25日58分02秒

You are correct. But what is the effect on flow which is to see the behaviour of "yield" ? I can change the algorithm in the name of mathmatics. Will it help to get different assessment of "yield" ?

2019年04月25日58分02秒