I was working with generator functions and private functions of a class. I am wondering
Below is an example snippet of my scenario.
class someClass():
def __init__(self):
pass
#Copy and paste mistake where yield ended up in a regular function
def __someFunc(self):
print "hello"
#yield True #if yielding in this function it isn't called
def __someGenerator (self):
for i in range(0, 10):
self.__someFunc()
yield True
yield False
def someMethod(self):
func = self.__someGenerator()
while func.next():
print "next"
sc = someClass()
sc.someMethod()
I got burned on this and spent some time trying to figure out why a function just wasn't getting called. I finally discovered I was yielding in function I didn't want to in.
I'll try to answer the first of your questions.
A regular function, when called like this:
val = func()
executes its inside statements until it ends or a return
statement is reached. Then the return value of the function is assigned to val
.
If a compiler recognizes the function to actually be a generator and not a regular function (it does that by looking for yield
statements inside the function -- if there's at least one, it's a generator), the scenario when calling it the same way as above has different consequences. Upon calling func()
, no code inside the function is executed, and a special <generator>
value is assigned to val
. Then, the first time you call val.next()
, the actual statements of func
are being executed until a yield
or return
is encountered, upon which the execution of the function stops, value yielded is returned and generator waits for another call to val.next()
.
That's why, in your example, function __someFunc
didn't print "hello" -- its statements were not executed, because you haven't called self.__someFunc().next()
, but only self.__someFunc()
.
Unfortunately, I'm pretty sure there's no built-in warning mechanism for programming errors like yours.