This question already has an answer here:
I'm making a Python irc bot. For some reason the yield statement in my join() method makes it skip the method altogether, but if I replace it with a return it works fine. However, I need to yield an error per each unsuccessful join attempt.
I have a join method of the bot that returns a server error command code response if the join is unsuccessful for some reason. It's None if the bot joins successfully.
unsuccessful = bot.join(channels)
I would be able to do:
if unsuccessful: for error in unsuccessful: print(error)
The join method looks like this
def join(self, channels): chan_errors = range(471, 480) # See RFC for commands 471-479 if isinstance(channels, str): channels = [channels,] for channel in channels: self.send('JOIN %s' % channel) for response in self.get_response('JOIN', chan_errors): # Verify if response.command in chan_errors: channels.remove(channel) yield response self.channels.append(channels)
If I switch the "yield response" with "return response" it runs the method.
The get_response method looks like
def get_response(self, commands, terminators=None): for msg in self.msg_gen(): self.handle(msg) if msg.command in commands: if terminators is None: return msg yield msg if msg.command in terminators: return msg
It receives messages from a message generator. The commands are the server command the caller is looking for and the terminators drop out of the generator when one is found. It's sort of like a coroutine.
Does anyone know what is happening here?
Do you understand what yield is and how to use generators? bot.join(channels) returns a generator; you need to iterate over that to get the values that it yields.
BrenBarn I'll edit the question to illustrate that I will be using 'unsuccessful' as a generator
In what way is it "not working"? What does it do? Are you saying it doesn't print anything in the loop?
It does not step into the join() method at all and runs the very next method call. No exceptions or anything.
It won't step into the join method until you begin to iterate over unsuccessful. That's how generators work.
Okay, I was going to go with the latter if I couldn't get this to work anyway. Otherwise I'd be pointlessly iterating through None. It'd be like going back to Java or other languages and having to return an array. I'm surprised I couldn't find this elsewhere. I figured the generator adds to the variable as it iterates. This makes sense now.
The link Mark Hildreth posted, The Python yield keyword explained, is one of the best (if not THE best!) resources for Python generators - much better than the pydocs! e-satis just kills it :D