我应该检查类型的构造的论点(以及在其他地方太)?
-
03-07-2019 - |
题
蟒蛇阻碍了检查类型。但在许多情况下,这可能是有用的:
检查的构造的论点。例如检查是敌人布尔、串词典等。如果我不和设置的对象是成员的争论就会造成问题。
检查功能的论点。
在特性。如果有人设置一个错误的价值或不同类型,我应该迅速作出反应。
解决方案
简单的答案是否,使用多态,异常等。
-
如果构造函数参数的类型错误,则在执行依赖于特定类型参数的代码时将抛出异常。如果它是一个奇怪的,域特定的东西,提出你自己的例外。环绕的代码块,可能会因try-except和handle错误而失败。因此最好使用异常处理。 (功能参数相同)
-
在属性中,适用相同的参数。如果要验证接收到的值,请使用断言检查其范围等。如果值类型错误,则无论如何都会失败。然后,处理AssertionError。
醇>
在Python中,您将程序员视为智慧生物!只需很好地记录您的代码(使事情变得明显),在适当的地方引发异常,编写多态代码等。将构造中的异常处理(仅适用于它)/错误留给客户端代码。
警告强>结果 将异常处理留给客户并不意味着你应该在不知情的用户身上丢掉很多垃圾错误。如果可能的话,处理由于构造错误或代码本身的任何其他原因而可能发生的异常。您的代码应该是健壮的。如果您无法处理错误,请礼貌地通知用户/客户端代码程序员!
注意强>结果 一般来说,构造函数的错误参数不是我担心的太多。
其他提示
答案是几乎总是"没有"。总的想法在蟒蛇,红宝石,以及其他一些语言的我们称作"鸭打字".你不应该关心的是什么东西,只有它是如何工作的。换句话说,"如果你想要的是一些江湖医生,你不需要检查它实际上是一个鸭子"。
在现实生活中,问题将在所有这些类型的检查,是无法替代的投入具有替代实现的。你可以检查字典但是我可以想到过的东西在这是不是一个词典,但实现dict API。
类型检查,只有检查的许多可能的错误代码。例如,它不包括范围内检查(至少不在Python).一个现代化的响应以断言,需要有类型的检查,这是更有效开发单元的测试,确保不仅是正确的,但还能是正确的。
另一种观点是,你应该把你的API用户同意的成年人,相信他们可以使用API正确。当然有些时候,输入检查是有用的,但这是不常见的比你想象的。一个例子是输入来源不可靠,就像从公共网络。
检查所有你喜欢的,你只需要明确。以下示例是来自模块在标准库中 - 它检查 extrasaction
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中可能没那么有用(正如其他人所说),但检查合法值可能是一个好主意。这是一个好主意的原因是软件将更接近错误的来源(它遵循失败快速原则)。此外,检查作为其他程序员和您自己的文档。更好的是,它是“可执行文档”,这很好,因为它的文档不能说谎。
检查参数的快速而肮脏但合理的方法是使用assert:
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
我用试试…除外…此建议中的其他
因为我想在测试成功时设置实例成员 ,即使代码已更改或扩充。显然,你没必要这样做。
对于函数参数和设置属性,我不会提前做这些测试,我只是使用提供的对象并对抛出的异常起作用,除非在长时间的过程之后将使用可疑对象。
"如果我不和设置的对象是成员的争论就会造成问题。"
请非常明确的确切清单"问题",将会造成以后。
它将不在所有的工作?这是什么尝试/除外块。
将它的行为"奇怪"?这真是罕见的,而是局限于"近地小姐"类型和运营商。标准例子是分裂。如果你预计整数,但有浮点,然后划分可以不做你想要的。但是,这是固定//,对/司运营商。
它将是完全错误的,但似乎仍然完成了吗?这真是罕见的,并且将需要一个漂亮的-精心制作的类型,使用标准的姓名,但并非标准的事情。例如
class MyMaliciousList( list ): def append( self, value ): super( MyMaliciousList, self ).remove( value )
除此之外,它很难得的事情"引起的问题"。请更新你的问题与的具体例子"的问题"。
正如达尔克所说,答案几乎总是“不”。在Python中,您通常不关心参数是某种类型,而是行为类似于某种类型。这被称为“ Duck Typing ”。有两种方法可以测试参数是否像给定类型一样:(1)您可以像使用它一样使用它,并在/如果没有或(2)时抛出异常)您可以定义一个界面来描述该类型应该的行为并测试该界面的一致性。
zope.interface 是我首选的界面Python的系统,但还有其他几个。使用其中任何一个,您可以定义一个接口,然后声明给定类型符合该接口,或者定义一个适配器,将您的类型转换为符合该接口的类型。然后,您可以断言(或根据需要进行测试)参数提供(在zope.interface术语中)该接口。