Как я могу "двойной возврат" через несколько функций в Python? - PullRequest
0 голосов
/ 21 мая 2018

У меня есть три функции, которые «стекаются» и вызываются внутри другой, например:

async def start_swings(self, server, user):
    try:
        while self.jailed[server.id][user.id]['current'] != 0:
            await self.get_question(server, user)
        else:
            await self.escape_jail(server, user)
    except KeyError:  # User isn't jailed
        pass

async def get_question(self, server, user):
    rnd = random.choice(range(2))
    if rnd == 0:
        await self.swing_math(server, user)
    elif rnd == 1:
        await self.swing_reverse(server, user)

async def swing_math(self, server, user):
    num1 = random.randint(1, 1000)
    num2 = random.randint(1, 1000)
    ops = ['+', '-']
    op = random.choice(ops)
    ans = int(eval(str(num1) + op + str(num2)))
    await self.bot.send_message(user, "**\N{HAMMER} It's going to take you `{}` more swings to break free.**\n```What is {} {} {}?```\n*I might doze off if you take too long to answer. If you don't get a reply from me within a few seconds, type `>swing`. If you try to use `>swing` as a way to reset your current question, you'll get a cooldown penalty.*".format(self.jailed[server.id][user.id]['current'], num1, op, num2))
    resp = await self.bot.wait_for_message(author=user)
    resp = resp.clean_content
    if resp == str(ans):
        await self.bot.send_message(user, "Correct. \N{WHITE HEAVY CHECK MARK} Take a swing.")
        self.jailed[server.id][user.id]['current'] -= 1
        dataIO.save_json('data/jail/jailed.json', self.jailed)
    elif resp == ">swing":
        return
    else:
        await self.bot.send_message(user, "Wrong. \N{CROSS MARK} Let me put that brick back in place.")
        self.jailed[server.id][user.id]['current'] += 1
        dataIO.save_json('data/jail/jailed.json', self.jailed)

В третьей функции вы увидите следующее утверждение:

elif resp == ">swing":
    return

Как я могу получить это для эффективного "двойного возврата", чтобы вместо этого он возвращался к start_swings вместо get_questions?Я довольно новичок в Python и не знаю точно, как это назвать.Я эффективно пытаюсь заставить выполнение этого скрипта полностью остановиться в этой области кода:

elif resp == ">swing":
   return

… вместо того, чтобы просто вернуть его к последней вызванной функции.

1 Ответ

0 голосов
/ 21 мая 2018

Вы не можете «вытолкнуть» стек вручную, как вы могли это сделать в прежние времена, но вы можете использовать исключение (даже если это считается плохой практикой, если исключение не генерируется «исключительно»):

Наследовать от исключения:

class DoubleReturnException(Exception):
     pass

Установить обработчик:

    while self.jailed[server.id][user.id]['current'] != 0:
        try:
            await self.get_question(server, user)
        except DoubleReturnException:
            pass
    else:

Затем вместо возврата просто:

raise DoubleReturnException

длявернитесь к except части обработчика (независимо от количества вызовов).

Определение собственного исключения необходимо , поскольку это гарантирует, что программа вернется по этой причине, а недля ValueError или любого другого исключения, которое может выдать программа.

Это должно оставаться исключительным случаем.Программирование, выбрасывая исключения повсеместно, приводит к «коду спагетти» и каким-то образом восстанавливает злое утверждение goto.Это может показаться вам интересным на последних этапах стабильного продукта, когда вы не можете разбить весь (некорректный) дизайн для конкретного случая (но лично мне никогда не приходилось использовать подобные приемы).

...