标签云

微信群

扫码加入我们

WeChat QR Code

产量不工作,但回报也[复制]

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.

2018年06月19日09分05秒

BrenBarn I'll edit the question to illustrate that I will be using 'unsuccessful' as a generator

2018年06月19日09分05秒

In what way is it "not working"? What does it do? Are you saying it doesn't print anything in the loop?

2018年06月19日09分05秒

It does not step into the join() method at all and runs the very next method call. No exceptions or anything.

2018年06月19日09分05秒

It won't step into the join method until you begin to iterate over unsuccessful. That's how generators work.

2018年06月19日09分05秒

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.

2018年06月19日09分05秒

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

2018年06月18日09分05秒