overriding bool() for custom class

27,288

Solution 1

Is this Python 2.x or Python 3.x? For Python 2.x you are looking to override __nonzero__ instead.

class test:
    def __nonzero__(self):
        return False

Solution 2

If you want to keep your code forward compatible with python3 you could do something like this

class test:
    def __bool__(self):
        return False
    __nonzero__=__bool__

Solution 3

If your test class is list-like, define __len__ and bool(myInstanceOfTest) will return True if there are 1+ items (non-empty list) and False if there are 0 items (empty list). This worked for me.

class MinPriorityQueue(object):
    def __init__(self, iterable):
        self.priorityQueue = heapq.heapify(iterable)
    def __len__(self):
        return len(self.priorityQueue)

>>> bool(MinPriorityQueue([])
False
>>> bool(MinPriorityQueue([1,3,2])
True

Solution 4

Similar to John La Rooy, I use:

class Test(object):
    def __bool__(self):
        return False

    def __nonzero__(self):
        return self.__bool__()

Solution 5

[this is a comment to the answer from @john-la-rooy but I cannot comment yet :) ]

For Python3 compatibility you can do (I was looking for this)

class test(object):
    def __bool__(self):
        return False

    __nonzero__=__bool__

only problem is that you need to repeat the __nonzero__ = __bool__ everytime you change __bool__ in subclasses. Otherwise __nonzero__ will be kept from the superclass. You can try

from builtins import object  # needs to be installed !

class test(object):
    def __bool__(self):
        return False

    __nonzero__=__bool__

which should work (not confirmed) or write a metaclass :) yourself.

Share:
27,288
Ponkadoodle
Author by

Ponkadoodle

Updated on July 09, 2022

Comments

  • Ponkadoodle
    Ponkadoodle almost 2 years

    All I want is for bool(myInstance) to return False (and for myInstance to evaluate to False when in a conditional like if/or/and. I know how to override >, <, =)

    I've tried this:

    class test:
        def __bool__(self):
            return False
    
    myInst = test()
    print bool(myInst) #prints "True"
    print myInst.__bool__() #prints "False"
    

    Any suggestions?

    (I am using Python 2.6)

  • Ponkadoodle
    Ponkadoodle over 10 years
    That's handy. Thanks for this alternate solution.
  • TrinitronX
    TrinitronX over 9 years
    Thanks for this... I was looking for a way to test the __nonzero__ class method for testing False here
  • jhp
    jhp over 7 years
    Or use the approach from tknickman to avoid this issue. It will add another function call though!
  • Callam Delaney
    Callam Delaney almost 6 years
    This is actually the best solution as it is compatible with both Python3 and Python2 to my knowledge. Even if it is not an iterable you could implement something to mock it.
  • IceArdor
    IceArdor over 5 years
    __nonzero__ = __bool__ is the preferable way of aliasing __bool__ because it's less code (quicker to read, less to maintain), less likely to hide a bug (what happens if __bool__ later becomes an async function?), but more importantly 1 less stack frame for a frequently called function that's also implicit! The difference here is whether you're defining 2 functions or just 1 function that's referenced twice.
  • Leo Ufimtsev
    Leo Ufimtsev almost 5 years
    It would be of benefit to mention that bool is python3 and code to make a class more portable across python2/3 as mentioned by John below.
  • Leo Ufimtsev
    Leo Ufimtsev almost 5 years
    The nonzero__=__bool seems to how an error in python 2 because bool is not defined.
  • Zhang Fan
    Zhang Fan over 3 years
    @LeoUfimtsev have you moved "__nonzero__=__bool__" to a smaller line number than "def __bool__(self):" ? in that case it is undefined, written order matters here.
  • LMCuber
    LMCuber over 2 years
    Wouldn't this create a class variable instead of an instance variable?