Boolean tests [was Re: Attack a sacred Python Cow]

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Jul 30 22:41:08 EDT 2008


On Wed, 30 Jul 2008 09:23:05 -0600, Matthew Fitzgibbons wrote:

> If you're expecting a list (and only a list)
> then your point makes sense. 'if x' can get you into trouble if you
> _don't_ want its polymorphism.

"if x" is hardly unique in that way. If you're expecting a list, and only 
a list, "len(x) != 0" will get you in trouble if somebody passes a string 
or a dictionary. I don't see any reason why we should single out "if x" 
as dangerous in the face of invalid types. With the exception of the "is" 
and "is not" operators, nothing in Python is guaranteed to work with any 
imaginable object. Even print can fail, if the object's __str__ method 
raises an exception.

 
> Although, if my function is expecting a list, my preference is to do:
> 
> if not isinstance(x, list):
>      raise SomeMeaningfulException()
> # do stuff with the list
> 
> I put my type checking at the top of the function, so readers can
> reference it easily.

And thus you break duck-typing and upset anybody who wants to pass a 
sequence that doesn't inherit directly from list.

There are other (and arguably better, although more labour-intensive) 
techniques for defensive programming that don't break duck-typing. You 
can google for Look Before You Leap and Easier To Ask Forgiveness Than 
Permission for more information. Alex Martelli has a fine recipe in the 
Python Cookbook -- search for the recipe "Checking if an object has the 
necessary attributes".

But in a nutshell, here's a toy example:

def spam(seq):
    try:
        seq.append
        seq.extend
        seq[0] = seq[0]
    except Exception:
        raise TypeError("argument isn't sufficiently sequence-like")
    # No exceptions expected from here on
    seq.append(seq[0])
    seq.extend([1,2,3])
    seq[0] = "spam"




-- 
Steven



More information about the Python-list mailing list