我的基本理念是不要请求许可,只要去做并请求原谅。例如,它不需要是一个文件就可以有一个.read()方法,当你发现你想要读取一个类似文件的对象时,你会发现事情"只是工作"时,你会感谢自己。但是,对于像文件这样的复杂对象,这几乎比像数字这样的简单对象更容易理解。
所以我正在尝试编写一个非常简单的类。细节并不重要,但它有一个内部计数器,当计数器超过限制时必须做一些事情。创建对象时,限制作为参数提供。
现在我正在考虑防御性编程。显然,我希望我的极限是一个整数,或者至少是一个整数。它可能比这弱,因为如果我做的>= 测试仍然是浮点数,它仍然会提供正确的行为。
尽管类用户会知道这个参数应该是一个整数,但我希望对象做一些不令人惊讶的事情,如果它不是。我的第一个想法是检查我是否真的有一个数字
if isinstance(limit,(int,long,float)):
但是这里有许多"不要测试,尝试例外"的答案,所以我知道这是不pythonic的。最好使用限制,并等待引发异常。所以我在尝试中尝试了这个:除了各种类型的限制
if counter >= limit:
如果限制是 int 或浮点数,则按预期工作正常。然后,我做了一个字符串或元组的限制,与数字比较的对象没有任何明显或合理的定义,并等待捕获异常。但它执行,返回布尔值,并保持沉默。
所以我 RTFM,事实证明比较不会引发混合类型的异常,这与"容器中的 x"的操作有关,在任意类型上测试了相等性。对于不同类型的类型,它总是返回not_equal,但量级比较虽然一致,但是任意的。如果混合类型量级比较总是返回 False,我也许可以使用它,但它也会很高兴地返回 True。
如果我尝试在非数字上使用其他类似整数的行为,我会得到预期的异常,例如这个字符串 + 数字抛出一个 TypeError
limit+0
所以我可以说
if counter >= (limit+0)
如果限制不是数字,则会引发所需的异常。但这感觉几乎是混淆的。我正在对表达式做一些额外的事情,以通过后门进行类型测试。任何代码优化器或其他编辑器都会删除明显冗余的算术运算。这就像看这个物体是否和鸭子一样重,看看它是否是木头做的,所以可以像女巫一样被烧死(有点)。
更明显的可能性是
if counter >= int(limit)
其中至少有一些内置的解释。它并没有完全按照我在所有情况下想要发生的事情去做,但它目前已经足够了,它不会让任何人感到惊讶。
那么WWGD?当你只想比较它的量级时,使用不受信任的参数的 pythonic 方法是什么?
如果您确实想验证参数是否属于合适的数字类型,请测试它是否是适当的数字抽象基类的实例,也许:
import numbers
...
if not isinstance(limit, numbers.Real):
... # react to the bad argument type
大概在这种情况下,你会抛出一个TypeError
异常。
在类的 __init__
方法中执行此操作,以便检测问题并报告尽可能接近调用方的原始错误。 这比等待一些不确定的时间并最终在程序开始使用计数器时爆炸要好得多,此时异常回溯在识别问题起源方面的帮助要小得多。
如果你感到偏执,你也可以在构造函数中检查这个参数的值是否大于零,如果不是,则抛出一个ValueError
异常。