When a function has empty yield
statement, the function will just return None
for the first iteration, so you can say that the function acts as generator that can be iterated only once and yields None value:
def foo():
yield
>>> f = foo()
>>> print(next(f))
None
>>> print(next(f))
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
That's what an empty yield
does. But when a function has empty yield
in between two block of code, it will execute the codes before yield
for the first iteration, and the codes after yield
will be executed on second iteration:
def foo():
print('--statement before yield--')
yield
print('--statement after yield--')
>>> f = foo()
>>> next(f)
--statement before yield--
>>> next(f)
--statement after yield--
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
So, it somehow allows you to pause the execution of a function in the middle, however, it throws StopIteration
Exception for the second iteration because the function doesn't actually yield
anything on the second iteration, to avoid this, you can pass a default value to next
function:
Looking at your code, your function is also doing the same thing
def draw_ui(self, graphics):
self._reset_components()
imgui.set_next_window_size(200, 200, imgui.ONCE)
if imgui.begin("Entity"):
if not self._selected:
imgui.text("No entity selected")
else:
imgui.text(self._selected.name)
yield #<--------------
imgui.end() #
So, while calling funciton draw_ui
, if control goes to else
block, then line outside the else block, i.e. imgui.end()
is not called until the second iteration.
This type of implementation is generally done to be used in ContextManager and you can relate to following code snippet copied from contextlib.contextmanager documentation
from contextlib import contextmanager
@contextmanager
def managed_resource(*args, **kwds):
# Code to acquire resource, e.g.:
resource = acquire_resource(*args, **kwds)
try:
yield resource
finally:
# Code to release resource, e.g.:
release_resource(resource)
>>> with managed_resource(timeout=3600) as resource:
... # Resource is released at the end of this block,
... # even if code in the block raises an exception