26

If statements in Python allow you to do something like:

   if not x:
       print "X is false."

This works if you're using an empty list, an empty dictionary, None, 0, etc, but what if you have your own custom class? Can you assign a false value for that class so that in the same style of conditional, it will return false?

Marcin
  • 48,559
  • 18
  • 128
  • 201
Kelketek
  • 2,406
  • 5
  • 21
  • 28
  • Does this answer your question? [Defining "boolness" of a class in python](https://stackoverflow.com/questions/8205558/defining-boolness-of-a-class-in-python) – iBug Apr 02 '22 at 13:56
  • @iBug that question is specifically about debugging a version compatibility problem. – Karl Knechtel Jan 15 '23 at 06:22

2 Answers2

38

You need to implement the __nonzero__ method on your class. This should return True or False to determine the truth value:

class MyClass(object):
    def __init__(self, val):
        self.val = val
    def __nonzero__(self):
        return self.val != 0  #This is an example, you can use any condition

x = MyClass(0)
if not x:
    print 'x is false'

If __nonzero__ has not been defined, the implementation will call __len__ and the instance will be considered True if it returned a nonzero value. If __len__ hasn't been defined either, all instances will be considered True.

In Python 3, __bool__ is used instead of __nonzero__.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • 16
    Note that it's `__bool__` in Python 3. –  Mar 20 '12 at 13:42
  • Will this only work if I have () on the end of it? I was hoping for a method that would work whether the item was an empty list, a 0, or an instance of my object that's false. Members of this class, integers, strings, etc, will all be in a list. I need a way to universally test if any of them are false. – Kelketek Mar 20 '12 at 14:00
  • 2
    @Kelketek: I fleshed out the example a little. There is no need to put `()` anywhere, it works just like for lists and numbers. – interjay Mar 20 '12 at 14:05
10
class Foo:
     def __nonzero__(self): return False
     __bool__ = __nonzero__ # this is for python3

In [254]: if Foo():
   .....:     print 'Yeah'
   .....: else: print 'Nay'
   .....:
Nay

Or, if you want to be ultra-portable, you can define __len__ only, which will have the same effect in both languages, but that has the (potential) downside that it implies that your object has a meaningful measure of length (which it may not).

This will work for any instance, depending on the actual logic you put in the method.

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • 2
    "it implies that your object has a meaningful measure of length", true words of wisdom about semantics here. – TaylorMac Oct 28 '15 at 17:04