【问题标题】:Trigger Break Keyword Using Dictionary Python使用字典 Python 触发中断关键字
【发布时间】:2016-08-20 03:01:13
【问题描述】:

我正在尝试弥补 Python 缺少 switch 语句的问题,并通过使用字典来提高代码效率,但我无法完全得到我想要的东西。这是我正在使用的代码的简化版本

def zero():
    print("Yo")


def one():
    print("Hey")

options = {
    0: zero,
    1: one,
}
while True:
    response = int(input("Number: "))
    try:
        options.get(response)()
    except TypeError:
        print("Not a valid response")

而我想看到的是某种打破循环的方法,例如退出循环的2: break。目前我正在使用 sys.exit(0),但想知道是否可以使用 break 关键字

【问题讨论】:

  • 当您说“弥补 Python 缺少 switch 语句的情况”时,您与哪种语言进行比较?在 C/C++ 的 switch 语句中,你会遇到类似的问题:break 只会退出 switch 语句,而你需要其他方式来退出循环(请参阅stackoverflow.com/questions/1420029/…)。

标签: python python-3.x dictionary switch-statement


【解决方案1】:

您可以定义一个LoopBreak 异常,在two 函数中引发它,然后在循环中将其捕获到break

class LoopBreak(Exception):
    pass    

def zero():
    print("Yo")

def one():
    print("Hey")

def two():
    raise LoopBreak

options = {
    0: zero,
    1: one,
    2: two
}

while True:
    response = int(input("Number: "))
    try:
        options.get(response)()
    except TypeError:
        print("Not a valid response")
    except LoopBreak:
        break

作为一个兴趣点,这类似于 Python 原生用于停止生成器的模式;当他们用完 yield 的值时,他们会引发 StopIteration 异常。

编辑:正如@mfripp 在下面正确指出的那样,这将掩盖在执行zeroone 期间引发的任何TypeErrors。我会把主循环改成这个(这样你就不必依赖TypeError):

while True:
    response = int(input("Number: "))
    action = options.get(response)
    if action is None:
        print("Not a valid response")
        continue
    try:
        action()
    except LoopBreak:
        break

【讨论】:

    【解决方案2】:

    有几种方法可以做到这一点。

    这是@BingsF 聪明答案的一个更强大的版本(这个不会掩盖所选函数中引发的异常):

    class LoopBreak(Exception):
        pass    
    
    def zero():
        print("Yo")
    
    def one():
        print("Hey")
    
    def two():
        raise LoopBreak
    
    options = {
        0: zero,
        1: one,
        2: two
    }
    
    while True:
        try:
            response = int(input("Number: "))
            action = options[response]
        except (ValueError, KeyError):
            print("Not a valid response")
            continue
    
        try:
            action()
        except LoopBreak:
            break
    

    或者你可以在你的字典中指定一个特殊的标志来强制中断:

    def zero():
        print("Yo")
    
    def one():
        print("Hey")
    
    options = {
        0: zero,
        1: one,
        2: False
    }
    
    while True:
        try:
            response = int(input("Number: "))
            action = options[response]
        except (ValueError, KeyError):
            print("Not a valid response")
            continue
    
        if action is False:
            break
        else:
            action()
    

    或者使用特殊的返回值来强制中断:

    def zero():
        print("Yo")
        # returns None by default
    
    def one():
        print("Hey")
        # returns None by default
    
    def two():
        return False
    
    options = {
        0: zero,
        1: one,
        2: two
    }
    
    while True:
        try:
            response = int(input("Number: "))
            action = options[response]
        except (ValueError, KeyError):
            print("Not a valid response")
            continue
    
        if action() is False:
            break
    

    以下代码可能更“Pythonic”。它可能比上述方法慢得多,因为它必须检查所有if 语句,而不是通过哈希在字典中查找函数。但它可能更易于阅读和维护。

    while True:
        try:
            response = int(input("Number: "))
        except ValueError:
            response = -1    # error flag
    
        if response == 0:
            print("Yo")
        elif response == 1:
            print("Hey")
        elif response == 2:
            break
        else:
            print("Not a valid response")
    

    【讨论】:

      【解决方案3】:

      这就是你所需要的:

      while True:
          response = int(input("Number: "))
          if response not in options:
              print("Not a valid response")
          else if response == 2:
              break
          else:
              options[response]()  # invoke the corresponding function
      

      顺便说一句,将函数存储在字典中并必须像这样调用它们并不完全是 Pythonic。用连续的ifs 简单地明确列举您需要的行为会好得多。

      【讨论】:

      • 是的,这部分有效,但我正在寻找退出循环的方法。
      • 好的,谢谢。你认为我应该放弃字典并坚持使用一堆 if 和 elif 语句吗?
      • @MANA624 我在实践中发现 if-else 只是让阅读代码更容易。使用字典通常最适合数据,您仍然可以使用字典来存储函数,但我在实践中发现显式枚举在代码维护方面实际上是一件非常好的事情。
      • @MANA624 如果您有很多 个已定义的函数,那么使用字典不是一个坏选择。任何最适合您感知的用例(包括可读性和长期维护)的东西都应该没问题。
      猜你喜欢
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      相关资源
      最近更新 更多