Boolean tests [was Re: Attack a sacred Python Cow]
Matthew Fitzgibbons
elessar at nienna.org
Thu Jul 31 15:07:59 EDT 2008
Matthew Fitzgibbons wrote:
> Steven D'Aprano wrote:
>> 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"
>>
>>
>>
>>
>
> Yes, I know it breaks duck typing, which is why I do it only very
> rarely, and never with e.g. sequence types. If I use ifinstance for type
> checking, it's because I need some _very_ specific class, almost always
> one that I wrote. My more usual use case for ifinstance is to figure out
> how to handle a particular object using introspection.
>
> That said, your example is still helpful. It's a good approach, and I
> should use it more often. Although I'd also lean toward hasattr and
> iscallable and ordinary ifs instead of the try ... except where
> possible. Depending on what you put in the try ... except, you risk
> masking legit exceptions.
>
> Ahhh, Programing. Where no rule of thumb seems to last five minutes.
>
> -Matt
> --
> http://mail.python.org/mailman/listinfo/python-list
>
Where by ifinstance I mean isinstance and by iscallable I mean callable.
*hides*
-Matt
More information about the Python-list
mailing list