【问题标题】:Raise statements: Why does my block of code return an empty list instead of executing my "raise" statement?提升语句:为什么我的代码块返回一个空列表而不是执行我的“提升”语句?
【发布时间】:2021-06-10 12:46:47
【问题描述】:

首先,如果我的问题被认为是愚蠢的,或者我的帖子中有任何错误,我深表歉意 - 这是我的第二篇帖子,我仍然很难在这个平台上提出适当的问题。

其次,我尝试使用 Python 文档网站 (https://docs.python.org/3/tutorial/errors.html) 和 Stackoverflow 上的另一篇文章 (Raise statement) 中的示例查找“raise”语句背后的逻辑,但我仍然无法理解这个“提高”声明。

我正在尝试回答电子书Introduction to Computing and Programming using Python中的以下问题:“实现满足规范的函数。” (请参阅下面的功能说明)。

def findAnEven(L):
    """
    ASSUMES: L is a list of integers 
    RETURNS: the first even number in L
    Raises ValueError if L does not contain an even number
    """

下面是我尝试解决这个问题:
def findAnEven(L):
    """
    ASSUMES: L is a list of integers
    RETURNS: the first even number in L
    Raises ValueError if L does not contain an even number
    """
    try:
        evenNumbers = []
        for i in L:
            if i % 2 == 0:
                evenNumbers.append(i)
                break
        return(evenNumbers)
    except ValueError:
        raise ValueError("ValueError exception thrown")
findAnEven([1,2,3,4]) # RETURNS: [2]
findAnEven([1,1,1,1]) # RETURNS: [] - THIS SHOULD EXECUTE RAISE STATEMENT, NOT RETURN AN EMPTY LIST            

我试图理解为什么我的代码块只返回一个空列表,而不是执行我的“raise”语句?

如果有人能解释(用外行的话)为什么我的代码块将一个空列表返回到最后一个函数调用(即 findAnEven([1,1,1,1]) 而不是执行我的“raise”语句,我将不胜感激 - 再次为这个愚蠢的问题道歉!

【问题讨论】:

  • 您好,感谢您的回复。我试图回答以下规范,如我的帖子中所述: def findAnEven(L): """ 假设:L 是整数列表返回:如果 L 不包含偶数,则 L 中的第一个偶数引发 ValueError number """ Python 电子书中的章节与“异常”相关,如果 L(应该是一个列表)不包含偶数,则与“引发 ValueError”相关的具体练习。我试图用我目前学到的知识来回答电子书中的问题,但发现它很棘手!

标签: python-3.x raise


【解决方案1】:
try:
    evenNumbers = []
    for i in L:
        if i % 2 == 0:
            evenNumbers.append(i)
            break
    return(evenNumbers)
except ValueError:
    raise ValueError("ValueError exception thrown")

except 块中的代码永远不会被执行,因为try 块中的任何行都不能引发ValueError。如果L 中没有偶数,则if 永远不会是Truereturn(evenNumbers) 只会返回空的evenNumbers 列表。

如果您想引发异常而不是返回空列表,请明确执行此操作。 我还冒昧地使您的代码更加pythonic和简洁。 一旦找到第一个偶数,它将返回一个包含它的列表。 如果return 语句从未被命中,则意味着没有找到偶数,因此我们提出ValueError 并带有明确的消息。

def find_an_even(L):
    """
    ASSUMES: L is a list of integers
    RETURNS: the first even number in L
    Raises ValueError if L does not contain an even number
    """
    
    for n in L:
        if n % 2 == 0:
            return [n]
            # or just 'return n' if you want to return the number not within a list
    raise ValueError("No even numbers in L")

【讨论】:

  • 嗨,DeepSpace,感谢您的回复,并为迟到的回复道歉,我在回复之前试图了解您写的内容。看来我没有问一个足够具体的问题,但你仍然设法理解我试图通过你的回答来实现什么 - “如果你想引发异常而不是返回一个空列表,请明确地做到这一点。”这正是我试图实现的目标,但失败了并产生了一个空列表。感谢您的解释和您的代码示例澄清,我也感谢“Pythonic”重构!
【解决方案2】:

首先,没有愚蠢的问题!每个人都按照自己的节奏学习。

Python 的 raise 是 Python 中与错误相关的一系列关键字的一部分(请参阅完整列表 here)。您应该知道的最重要的是tryexceptraise。我将在这里逐一解释:

  • try 始终与 except 配对,就像您在此处所做的那样。发生的情况是,try“范围内” 将像任何普通代码块一样执行。但是,如果发生了不好的事情(即您的代码做出了错误的假设或发生了错误)并且引发​​了 ValueError,则脚本不会立即终止或停止执行 - 相反,它会“冒泡”该错误将出现在下面的except 子句中,并允许您处理它,就像您在此处所做的那样。 但是,只有在执行 try 子句时实际提升了 ValueError 时,才会执行 except 子句中的内容。如果try 子句中的代码执行没有任何问题,那么except 子句的代码永远不会执行 - 它会被完全跳过。
  • 一旦问题冒泡到except 子句,您可以让它打印一些东西或做任何您想做的事情,然后使用raise 关键字强制它实际停止执行,这会人为地在您的内部创建一个错误错误处理程序(即except 子句)。

在您的示例中,ValueError 永远不会在任何地方引发(因为您的代码不会中断),因此永远不会调用 except 子句的代码!我认为您将“错误”与 False 混为一谈。在您的示例中,findAnEven([1,1,1,1]) 完美执行 - 它返回一个空列表,因为您传递的列表中确实没有偶数。没有偶数的事实不是错误 - 这只是关于您输入的列表的事实。

【讨论】:

  • 嗨@victor__von__doom,感谢您的回复并为迟到的回复道歉。就像您之前的 Deepspace 的 cmets 一样,我只是想在回复之前完全理解所建议的内容。您的观点非常有见地,感谢“冒泡”的类比,这是思考 except 子句的一种有趣方式。
猜你喜欢
  • 2014-02-19
  • 2021-07-07
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 2021-01-04
  • 2017-07-02
  • 2017-01-23
相关资源
最近更新 更多