【问题标题】:Raising pythonic exception引发pythonic异常
【发布时间】:2016-08-31 05:24:05
【问题描述】:

Python 3.5.1.. 我有一些代码需要用来引发异常。我想知道这是否是“pythonic”的方式。我在其他地方被告知我应该使用 try/except,但是,在这种情况下,我被特别指示使用:

  • if:raise /else
  • Lo​​cationError 必须接受一个输入,位置
  • Lo​​cationError 必须继承自 Exception 类

鉴于这些限制,有没有“更好”的方法来做到这一点?

location = [1, 2]

def update_loc(oldloc, newloc):
    if oldloc == newloc:
        raise LocationError('Location match, old location = {0}'.format(newloc))
    else:
        oldloc = newloc
    return oldloc

class LocationError(Exception):
    def __init__(self, location):
        self._location = location #initial code
        super().__init__(location) #fixed code

location = update_loc(location, [1, 2])

所以,有人告诉我,问题是我没有从 Parent 类继承(异常)。我猜想为异常创建一个子类的意义就是这样,仅此而已。

【问题讨论】:

  • 您的字符串格式出现在错误的位置。
  • 我不知道为什么你被告知应该使用 try/except 但应该在这里引发异常。其中一个加注,另一个接球。这就像说您应该从根本上返回一个值,但在这种情况下,您的函数需要接受一个参数。引发异常完全没问题,捕获它们也是如此。
  • 它应该在哪里发生,我在问,因为我是根据我读过的例子写的,但感觉有些不对劲。
  • 韦恩你的意思是像e = LocationError(newloc)raise e
  • 我会考虑让你的自定义异常扩展一些更具体的东西,比如ValueError。请注意,文档说“在内置...时引发”,但这并不意味着您不能自己扩展它(或只是使用它);文档正在解释 Python 何时会提出此问题。

标签: python python-3.x exception python-3.5


【解决方案1】:

从您的描述中完全不清楚,但我怀疑您需要

  1. 定义LocationError异常类,
  2. 如果存在位置匹配,请在 update_loc 函数中引发该异常,并且
  3. try..except 块内调用 update_loc 以捕获异常。

这里有一些代码可以做到这一点。

class LocationError(Exception):
    def __init__(self, location):
        self.location = location

def update_loc(oldloc, newloc):
    if oldloc == newloc:
        raise LocationError(newloc)
    return newloc

location = [1, 2]

for data in ([1, 2], [3, 4], [3, 4], [1, 2]):
    try:
        location = update_loc(location, data)
        print('New location = {0}'.format(location))
    except LocationError as e:
        print('LocationError: new location matches old location = {0}'.format(e.location))

输出

LocationError: new location matches old location = [1, 2]
New location = [3, 4]
LocationError: new location matches old location = [3, 4]
New location = [1, 2]

请注意,在update_loc 中分配给oldloc 没有意义:这只会创建一个位于update_loc 本地的新列表。但是,由于这些位置是列表,因此可以在函数内改变它们。

例如,你可以这样做

def update_loc(oldloc, newloc):
    if oldloc == newloc:
        raise LocationError(newloc)
    oldloc[:] = newloc

location = [1, 2]

for data in ([1, 2], [3, 4], [3, 4], [1, 2]):
    try:
        update_loc(location, data)
        print('New location = {0}'.format(location))
    except LocationError as e:
        print('LocationError: new location matches old location = {0}'.format(e.location))

这将产生与早期代码相同的输出。

【讨论】:

  • 对不起,我一开始并不清楚,我已经更新了。一位知识渊博的朋友告诉我,我应该使用 try/except,但是我的课堂教学是使用 if, raise/else。编辑:只需要做前两个,谢谢
【解决方案2】:

您似乎混淆了一些概念。一般来说,异常处理定义了你如何处理你试图做一些不可能的事情的情况。在 python 中,您会引发一个异常,您可以排除并处理它。

i = input("Give me a number")
try:
    # the following line will raise an ZeroDivisionError
    print(5/i)
except ZeroDivisonError:
    print("You can't insert 0")

如果检测到错误状态,您也可以手动引发异常/错误:

class Person

    def __init__(self, age):
        if age < 0:
            raise ValueError("Age can't be below zero")

实际上没有其他方法可以引发异常。

但是有多种方法可以处理异常。第一个是尽可能多地阻止它们(在你跳跃之前查看,称为 LBYL)。

age = input("What is your age?")
if age < 0:
    print("You can't be of a negative age.")
    exit(1)
person = Person(age)

或者您可以简单地尝试做您想做的事并在以后捕获任何异常:

age = input("What is your age?")
try:
    person = Person(age)
except ValueError:
    print("You can't be of a negative age.")

这通常被称为“请求宽恕比请求许可更容易”(称为 EAFP)。

在 python 中,一般首选 EAFP。

【讨论】:

    猜你喜欢
    • 2014-10-25
    • 1970-01-01
    • 2013-08-02
    • 2012-10-10
    • 1970-01-01
    • 2016-02-24
    • 2019-12-08
    • 2016-09-28
    • 1970-01-01
    相关资源
    最近更新 更多