Default __nonzero__ impl doesn't throw a TypeError exception

Terry Reedy tjreedy at
Fri Jan 9 21:58:56 CET 2009

Bruno Desthuilliers wrote:

> To be more exact: there's no "default __nonzero__".

In Py3, '__nonzero__' has been renamed to __bool__.
All objects are instances of class object,
which indeed has no __bool__ method to be a default
(it does have default __hash__ and __eq__, etc).

 > The boolean value of
> an object is eval'd this way:
> If the object is None (special cased by the interpreter AFAICT), it is 
> false.

Must be, since None.__bool__ does not exist.

> Else if the object implements __nonzero__, it has the boolean value 
> returned by __nonzero__.

Leaving None aside, __bool__ is only needed for non-collection classes 
(which do not have __len__) if at least 1 instance of the class is 
intended to be False.  For built-in classes, this means numbers.

> Else if the object implements __len__, it has the boolean value of its 
> length.

This method, interpreted more generally as 'object count', essentially 
defines collection classes.

> Else if is true.

Thank you for the clarification.  Then the __new__ method of class bool 
  would be implemented in Python as

def __new__(cls, ob):
   if ob is None:
     return False
   elif hasattr(ob, '__bool__'):
     b = ob.__bool__()
     if b.__class__ is bool:
       return b
        raise TypeError("__bool__ should return bool, returned %s" %
   elif hasattr(ob, '__len__'):
     return len(ob) != 0
     # ob.__len__() != 0 does not do len's typecheck on return
     return True

Experiments show that 3.0 bool.__new__ does typecheck the return of 
ob.__bool__ and raises the error indicated and that __len__ must return 
a value that passes len's typecheck.

Terry Jan Reedy

More information about the Python-list mailing list