How to validate the __init__ parameters

Steve Holden steve at holdenweb.com
Mon Dec 21 21:47:06 EST 2009


r0g wrote:
> Steven D'Aprano wrote:
>> On Mon, 21 Dec 2009 21:49:11 +0000, r0g wrote:
>>
>>> I use assertions myself e.g.
>>>
>>>>>> foo = "123456"
>>>>>> assert len(foo) <= 5
>>> Traceback (most recent call last):
>>>   File "<stdin>", line 1, in <module>
>>> AssertionError
>>>
>>>
>>> Dunno if this would be considered good or bad programming practice by
>>> those more experienced than I (comment always welcome!) but it works for
>>> me :)
>>
>> Bad practice.
>>
>> Assertions are ignored when you run Python with the -O (optimization) 
>> command line switch. Your code will behave differently if you use 
>> assertions. So you should never use assertions for error-checking, except 
>> perhaps for quick-and-dirty throw-away scripts.
>>
>> Assertions are useful for testing invariants and "this will never happen" 
>> conditions. A trivial example:
>>
>> result = math.sin(2*math.pi*x)
>> assert -1 <= result <= 1
>>
>> Assertions are also useful in testing, although be careful: since the 
>> assert statement is ignored when running with -O, that means you can't 
>> test your application when running with -O either! But do not use them 
>> for data validation unless you're happy to run your application with no 
>> validation at all.
>>
>>
>>
> 
> 
> Yikes, glad to be set me straight on that one! Thanks :) It's a pity
> though, I really like the way it reads. Is there anything similar with
> ISN'T disabled when optimizations are turned on?
> 
> I guess I could do the following but it seems a bit ugly in comparison :(
> 
> if len(foo) <= 5: raise Exception
> 
OK,so here's a revolutionary thought. Since you have now discovered that

a) you can't reliably rely on an AssertionError being raised by an
assert that asserts an invariant;

b) the alternative of explicitly raising an exception is at least
somewhat uglier; and

c) you have to do *something*. Er, actually, do you?

What's the exact reason for requiring that a creator argument be of a
specific type? So operations on the instances don't go wrong? Well, why
not just admit that we don't have control over everything, and just *let
things go wrong* when the wrong type is passed?

What will then happen? Why, an exception will be raised!

You might argue that the user, seeing the traceback from the exception,
won't know what to make of it. In response to which I would assert (pun
intended) that neither would the traceback produced by the assertion
failure.

Given that somebody who knows what they are talking about has to cast
their eye over a traceback to understand what's wrong with the program,
it's not much extra effort for that person realise that a method has
been called with an invalid argument type. I accept that there are
legitimate arguments in opposition to this point of view, but it has a
certain engineering efficiency (as long as we are prepared to work
inside frameworks like Django that will encapsulate any error tracebacks
so that you see all the information that you need, and the user gets
some other inexplicable error message like "A programmer probably
screwed up).

In other words, "be prepared to fix your program when it goes wrong" is
a valid alternative to trying to anticipate every single last thing that
might go wrong. This philosophy might not be appropriate for
extra-terrestrial exploration, but most Python programmers aren't doing
that.

regards
 Steve
-- 
Steve Holden           +1 571 484 6266   +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010  http://us.pycon.org/
Holden Web LLC                 http://www.holdenweb.com/
UPCOMING EVENTS:        http://holdenweb.eventbrite.com/



More information about the Python-list mailing list