On Wed, 28 Aug 2013 18:09:22 -0300, Joe Junior wrote: > While designing a simple library, I found myself asking a philosophical > question: to check or not to check the parameter's interface?
The only correct answer to that is, "Yes no maybe". :-) > I think that, considering it is Python, the usual answer would be "no", > but here is the situation that got me thinking: > > class Flock: > > def __init__(self): > self.ducks= [] > > def do_stuff(self): > for duck in self.ducks: > duck.quack() > > class Duck: > > def quack(self): > #quack-quack > pass > > f = Flock() > d = Duck() > f.ducks.append(d) > f.do_stuff() > > Ok, no big deal there, the problem is if the user forgets to implement > the quack() method. The stack trace would complain that "duck.quack()" > is wrong, but that can happen hundreds of lines after the user actually > added the object to the Flock, and it can be hard to find out what is > happening and which object is wrong. True, but that's a good case for improving the error message, or using a debugger. Here is Flock.do_stuff re-written to give a more verbose/useful error message: def do_stuff(self): for i, duck in enumerate(self.ducks): try: duck.quack() except AttributeError: raise DuckError( 'object %r at index %d has no quack' % (duck, i) ) Okay, seeing the index is useful. But we would have got nearly as much information from the AttributeError traceback, minus the index: py> (42).quack() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute 'quack' So how much extra work are you prepared to put in to make a rare occurrence (passing a magpie instead of a duck) easier to debug? Since errors are presumably rare, maybe the answer is "not a lot of extra work". But if the consequence of an error is catastrophic ("for want of a duck quacking, the nuclear reactor explodes, making the northern hemisphere uninhabitable"), maybe the answer is "as much as it takes". Other questions: what happens if duck.quack is buggy and raises AttributeError? A good question, but just how far should we go in worrying about things like this? What happens if duck.quack is buggy and raises StopIteration? Sometimes the right reaction is to deal with it if and when it actually occurs. In other words, wait for the bug report before trying to fix it. ("Fix it" may mean telling people "don't do that!".) > Of course I don't want to check isistance(), I like duck typing, but > should I check if hasattr() and callable() before adding to the > container? What is the pythonic way to deal with it? Am I worrying too > much ;-)? Yes :-) Except in the (rare?) case that you aren't worrying enough, in which case you can check hasattr and callable up front, or do whatever other tests you feel the need to check. It depends on the specific code you are writing. -- Steven -- http://mail.python.org/mailman/listinfo/python-list