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



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
.



Relevant Pages

  • Re: Boolean tests [was Re: Attack a sacred Python Cow]
    ... "len!= 0" will get you in trouble if somebody passes a string or a dictionary. ... With the exception of the "is" and "is not" operators, nothing in Python is guaranteed to work with any imaginable object. ... 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. ...
    (comp.lang.python)
  • Re: ObjectId_to_string gives exception
    ... client by following code. ... I think the problem is that the objectID (sequence of octets) contains ... CORBA::BAD_PARAM exception being thrown but you're not catching it. ... If conversion of an ObjectId to a string would ...
    (comp.object.corba)
  • C++ Binding: Sequence allocbuf/freebuf
    ... I've checked the TAO and MICO sequence implementation and both appear ... Is the TAO and MICO implementations non conforming? ... C++ dialects without exception handling (especially for ctors ...
    (comp.object.corba)
  • Re: Pure Patterns (was: The Collatz discrete primes!)
    ... has telescoping values of impures also. ... You have the sequence being ... repetition rate that's a power of 3 (the Y term of the ... the exception repeat rate will always be 2 times ...
    (sci.math)
  • Error when attaching multiple files (System.web.mail)
    ... I am having some trouble using the MailMessage object to send an email with ... Exception has been thrown by the target of an invocation. ... When a user submits a file, it is stored directly to the database, and when ...
    (microsoft.public.dotnet.framework.aspnet)