Python 我是否应该检查构造函数参数的类型(以及在其他地方)?
Python不鼓励检查类型。但在许多情况下,这可能是有用的:Python 我是否应该检查构造函数参数的类型(以及在其他地方)?,python,typechecking,Python,Typechecking,Python不鼓励检查类型。但在许多情况下,这可能是有用的: 检查构造函数参数。e、 g.检查布尔值、字符串、dict等。如果我不这样做,并将对象的成员设置为参数,它将在以后导致问题 检查函数参数 在属性中。如果有人设置了错误的值或不同的类型,我应该快速响应 简单的答案是否定,使用多态性、异常等 如果构造函数参数的类型错误,则在执行依赖于特定类型参数的代码时将引发异常。如果这是一件奇怪的、特定于领域的事情,请提出您自己的异常。环绕可能因“尝试除外”和“处理错误”而失败的代码块。因此,最好使用异常
简单的答案是否定,使用多态性、异常等
将异常处理留给客户机并不意味着您应该向不知情的用户抛出大量垃圾错误。如果可能的话,处理可能由于代码本身的错误构造或任何其他原因而发生的异常。您的代码应该是健壮的。如果您无法处理错误,请礼貌地通知用户/客户端代码程序员 注意
一般来说,我并不太担心构造函数的错误参数。检查所有你喜欢的,你只需要显式。以下示例是标准库中的构造函数-它检查
extraction
arg:
class DictWriter:
def __init__(self, f, fieldnames, restval="", extrasaction="raise",
dialect="excel", *args, **kwds):
self.fieldnames = fieldnames # list of keys for the dict
self.restval = restval # for writing short dicts
if extrasaction.lower() not in ("raise", "ignore"):
raise ValueError, \
("extrasaction (%s) must be 'raise' or 'ignore'" %
extrasaction)
self.extrasaction = extrasaction
self.writer = writer(f, dialect, *args, **kwds)
答案几乎总是“不”。Python、Ruby和其他一些语言中的一般思想称为“”。你不应该关心什么东西,只关心它是如何工作的。换句话说,“如果你想要的只是一只鸭子,你不需要检查它是否真的是一只鸭子。” 在现实生活中,进行所有这些类型检查的问题是无法用替代实现替换输入。您可以检查dict,但我可能希望传递的内容不是dict,而是实现dictapi 类型检查只检查代码中许多可能的错误之一。例如,它不包括范围检查(至少在Python中不包括)。对需要进行类型检查的断言的现代回应是,开发单元测试更有效,它不仅确保类型正确,而且确保功能正确 另一种观点是,你应该像成年人一样对待你的API用户,相信他们会正确使用API。当然,有时输入检查是有帮助的,但这并不像你想象的那么普遍。一个例子是来自不受信任的来源的输入,如来自公共网站的输入。“如果我不这样做,并将对象的成员设置为参数,则稍后会导致问题。” 请非常清楚以后将导致的“问题”的确切清单
- 这根本行不通吗?这就是try/except块的用途
- 它会表现得“奇怪”吗?这种情况非常罕见,仅限于“未遂”类型和运算符。标准的例子是除法。如果您期望的是整数,但得到的是浮点,那么除法可能无法满足您的要求。但对于//,vs/除法运算符,这是固定的
- 它是否仅仅是错误的,但仍然看起来是完整的?这是非常罕见的,需要一个非常精心制作的类型,使用标准名称,但做非标准的事情。比如说
class MyMaliciousList( list ): def append( self, value ): super( MyMaliciousList, self ).remove( value )
除此之外,很难让事情“以后再出问题”。请用“问题”的具体例子更新您的问题。这通常是一件好事。在Python中检查显式类型可能没有那么有用(正如其他人所说),但检查合法值可能是一个好主意。这是一个好主意的原因是,软件将在更接近错误源的地方发生故障(它遵循快速故障原则)。此外,这些检查还可以作为其他程序员和您自己的文档。更好的是,它是“可执行文档”,这是好的,因为它是不会说谎的文档 检查您的参数的一种快速、肮脏但合理的方法是使用断言:
def my_sqrt(x):
assert x >= 0, "must be greater or equal to zero"
# ...
坚持你的论点是一种穷人的契约设计。(您可能希望查找契约式设计;这很有趣。)AFAIU,您希望确保某些对象的行为(“遵循接口”)早于实际使用的时间。在您的示例中,您希望知道对象在实例创建时是合适的,而不是在实际使用时 请记住,我们在这里讨论的是Python,我不建议使用
assert
(如果在程序运行时Python-O
或环境变量PYTHONOPTIMIZE设置为1会怎么样?)或检查特定类型(因为这不必要地限制了您可以使用的类型),但我建议提前测试功能,大致如下:
def __init__(self, a_number, a_boolean, a_duck, a_sequence):
self.a_number= a_number + 0
self.a_boolean= not not a_boolean
try:
a_duck.quack
except AttributeError:
raise TypeError, "can't use it if it doesn't quack"
else:
self.a_duck= a_duck
try:
iter(a_sequence)
except TypeError:
raise TypeError, "expected an iterable sequence"
else:
self.a_sequence= a_sequence
我在这个建议中使用了try…except…else
,因为我只想在测试成功时设置实例成员,即使代码被更改或扩充。显然,你不必这么做
对于函数参数和设置属性,我不会提前进行这些测试,我只会使用提供的对象并对t进行操作