[英]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.