Steven D'Aprano wrote:
On Sun, 27 Jul 2008 23:45:26 -0700, Carl Banks wrote:

I want something where "if x" will do but a simple explicit test won't.

Explicit tests aren't simple unless you know what type x is.

If you don't even know a duck-type for x, you have no business invoking any methods on that object.

If you do know a duck-type for x, then you also know which explicit test to 
perform.

Explicit tests are not necessarily simple for custom classes. Testing for emptiness could be arbitrarily complex. That's why we have __nonzero__, so you don't have to fill your code with complex expressions like (say)

if len(x.method()[x.attribute]) > -1

Instead you write it once, in the __nonzero__ method, and never need to think about it again.

Okay, so you have this interesting object property that you often need to test for, so you wrap the code for the test up in a method, because that way you only need to write the complex formula once. I'm with you so far. But then you decide to name the method "__nonzero__", instead of some nice descriptive name? What's up with that?

This is the kind of code I would write:
   class C:
      def attribute_is_nonnegative(self):
         return len(self.method()[self.attribute]) > -1
   ...
   c = get_a_C()
   if c.attribute_is_nonnegative():
      ...

Now suppose you were reading these last few lines and got to wondering if get_a_C might ever return None.

The answer is obviously no. get_a_C must always return a C object or something compatible. If not, it's a bug and an AttributeError will ensue. The code tells you that. By giving the method a name the intent of the test is perfectly documented.

In comparison, I gather you would write something like this:
   class C:
      def __nonzero__(self):
         return len(self.method()[self.attribute]) > -1
   ...
   c = get_a_C()
   if c:
      ...

Again, the question is, can get_a_C return None? Well that's hard to say really. It could be that "if c" is intended to test for None. Or it could be intended to call C.__nonzero__. Or it could be cleverly intended to test not-None and C.__nonzero__ at the same time. It may be impossible to discern the writer's true intent.

Even if we find out that C.__nonzero__ is called, what was it that __nonzero__ did again? Did it test for the queue being non-empty? Did it test for the queue being not-full? Did it test whether for the consumer thread is running? Did it test for if there are any threads blocked on the queue? Better dig up the class C documentation and find out, because there is no single obvious interpretation of what is means for an object to evaluate to true.

"if x" is simple to type, but not so simple to read. "if x.namedPredicate()" is harder to type, but easier to read. I prefer the latter because code is read more often than it is written.

regards,
Anders
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to