look at the match_regex coroutine first rememberit doesn' execute any code when it is constructedratherit just creates coroutine object once constructedsomeone outside the coroutine will eventually call next(to start the code runningat which point it stores the state of two variablesfilename and regex it then reads all the lines in the file and iterates over them in reverse each line is compared to the regular expression that was passed in until it finds match when the match is foundthe coroutine yields the first group from the regular expression and waits at some point in the futureother code will send in new regular expression to search for note that the coroutine never cares what regular expression it is trying to matchit' just looping over lines and comparing them to regular expression it' somebody else' responsibility to decide what regular expression to supply in this casethat somebody else is the get_serials generator it doesn' care about the lines in the filein fact it isn' even aware of them the first thing it does is create matcher object from the match_regex coroutine constructorgiving it default regular expression to search for it advances the coroutine to its first yield and stores the value it returns it then goes into loop that instructs the matcher object to search for bus id based on the stored device idand then serial number based on that bus id it idly yields that serial number to the outside for loop before instructing the matcher to find another device id and repeat the cycle basicallythe coroutine' (match_regexas it uses the regex yield syntaxjob is to search for the next important line in the filewhile the generator' (get_serialwhich uses the yield syntax without assignmentjob is to decide which line is important the generator has information about this particular problemsuch as what order lines will appear in the file the coroutineon the other handcould be plugged into any problem that required searching file for given regular expressions closing coroutines and throwing exceptions normal generators signal their exit from inside by raising stopiteration if we chain multiple generators together (for exampleby iterating over one generator from inside another)the stopiteration exception will be propagated outward eventuallyit will hit for loop that will see the exception and know that it' time to exit the loop coroutines don' normally follow the iteration mechanismrather than pulling data through one until an exception is encountereddata is usually pushed into it (using sendthe entity doing the pushing is normally the one in charge of telling the coroutine when it' finishedit does this by calling the close(method on the coroutine in question