2

I typically use "is not None" to test whether an Object is empty or not. I am seeing code just use 'if object'. Are they the same thing?

for example,

if Dog:
  ...

VS

if Dog is not None:
  ...
ling
  • 1,555
  • 3
  • 18
  • 24
  • 4
    `if Dog is not None` works if Dog is `False`, but the first doesn’t. The first checks the truthiness and the second checks for things that aren’t `None` exclusively. – N Chauhan Jun 28 '19 at 15:43
  • What about if Dog can only be None or not None? In that case, I can simply use 'if Dog' test? – ling Jun 28 '19 at 15:46
  • 2
    `import this` -> "Explicit is better than implicit." – dallonsi Jun 28 '19 at 15:46
  • 1
    Doing `if object:` returns true if `object` is *falsey* - any value that resolves to false, including but not limited to `0`, `[]`, `""`, `{}`, `False`, and `None`. The comparison `if object is None` is more limited, because it only checks for one of those values. – Green Cloak Guy Jun 28 '19 at 15:48
  • `[] is not None`, `{} is not None`, `'' is not None`. I think you should reconsider how you "typically" test for emptiness. Typical use is not to test for `None`-ness, but to test whether the object is truthy. Empty lists, dicts, zero-length strings, etc. are all falsey. – David Zemens Jun 28 '19 at 15:48

1 Answers1

6

The syntax if Dog calls the __bool__ (or __len__) magic method of class Dog to get its boolean representation.

Some modules implement their object's __bool__ method such that it will raise an exception if called such as pandas:

ValueError: The truth value of a Series is ambiguous...

Though by default objects will return True if neither of those magic methods are implemented. Most builtins implement the __bool__ or __len__ magic method so using them in an if statement is normal.

So for a list you can just do:

my_list = []
if my_list:
    print("List has objects in it") # This will not be called with this code.

Classes will, by default, return True:

class Foo():
    # Classes do this by default
    # def __bool__(self):
    #     return True
    pass
f = Foo()
if f:
     print("This variable references an object") # This will be called

You can implement your class in such a way that python can better understand what is considered Truthy and what is considered Falsey:

class Foo():
    def __init__(self):
        self.my_list = []
    def append(self, ele):
        self.my_list.append(ele)
    # I could implement this instead of `len`
    # def __bool__(self):
    #     # Some object will raise an exception here
    #     return bool(self.my_list)
    def __len__(self):
        return len(self.my_list) > 1

f = Foo()
print("True") if f else print("False") # False
f.append(2)
print("True") if f else print("False") # False
f.append(2)
print("True") if f else print("False") # True

To read more see truth value testing