繁体   English   中英

Python异常处理 - 如何做到pythonic?

[英]Python exception handling - How to do it pythonic?

我还在学习Python programmimg语言。 我在代码异常方面问自己,当需要以pythonic方式处理这种情况时。 我读了几遍“你永远不应该默默地传递错误”。

例如一个小功能:

def square(list_with_items):
    return [i**2 for i in list_with_items]

如果有人将元组作为参数传递,是否需要编写错误处理程序? 或者,当我必须检查用户输入的验证时,它更有意义吗?

在检查类型的特定情况下,“Pythonic”要做的就是不检查它们。 除非有充分的理由,否则你应该假设呼叫者传递的是合理类型(注意:“明智的类型”可能与“你期望的类型”不同),并尽力返回合理的东西。 如果呼叫者传递的是一种不合理的类型,那么让他们处理后果是完全可以接受的。

例如,有人可能明智地将Decimal数字的迭代器传递给square函数:

>>> from decimal import Decimal
>>> square(Decimal(line.strip()) for line in open("numbers.txt")
[Decimal("4.0"), Decimal("9.0"), ...]

一切都会奏效! 但明确检查类型会使该用例更加困难。

然后,例如,如果有人传递了一些不合理的东西,他们就可以处理错误:

>>> square(42)
…
TypeError: 'int' object isn't iterable

此错误消息还将(在脚本中)包含调试问题所需的所有文件名和行号。

另一方面,当调用者可能会出现令人惊讶的后果时,显式检查参数有时很有用。 例如,如果你正在编写一个函数,它会在list表现出非常糟糕的性能,因为它需要deque ,那么检查if not isinstance(input, deque): raise TypeError("a deque must be used!")可能是有道理的。

这种“处理类型的方法”的名称叫做Duck Typing

你可以使用一个断言:

def square(list_with_items):
    assert(all([type(x) == int for x in list_with_items]))
    return [i**2 for i in list_with_items]

你可以使用两个断言:

def square(list_with_items):
    assert(type(list_with_items) in (list, tuple))
    assert(all([type(x) == int for x in list_with_items]))
    return [i**2 for i in list_with_items]

你可以使用断言和try / catch:

def square(list_with_items):
    assert(type(list_with_items) in (list, tuple))
    try:
        return [i**2 for i in list_with_items]
    except TypeError:
        raise Exception("Each element of the argument must be a number.")

这取决于。 在该具体示例中,如果您要以“只读”的方式使用“square”的返回值,则不应该有一个“真正的错误”将元组作为参数传递。 这是因为即使元组是不可变的,你的函数也会返回一个带有第一个元素的平方的新元组。

无论如何,我建议你使用一个简单的if-else语句来更精确地避免问题(例如:如果你将来以不同的方式调用这个函数):

def square(list_with_items):
    if isinstance(list_with_items, list): # True if list_with_items is a list - False otherwise
        return [i**2 for i in list_with_items]
    else:
        return 'Error: type(list_with_items) must be a list!'

编辑:如果您愿意(如果您要使用try-except语句捕获异常),则可以在else语句中使用“raise Exception”:

else:
    raise Exception('Error: type(list_with_items) must be a list!')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM