0

When an IF statement is called on an instance of a list object, is there a magic method that is used to evaluate whether True or False is returned? For example,

a = []
b = [1, 2, 3]

if a == b:  #  <---- __eq__() is called and returns False
    pass

if a:       #  <---- what is called here that returns False?
    pass

Is it: a.__bool__ (a.__nonzero__)? a.__len__?

or something else completely?

Alvin C
  • 127
  • 1
  • 11
  • 5
    The document says both `__bool__()` and `__len__()` are used https://docs.python.org/3/library/stdtypes.html#truth-value-testing – ymonad Mar 26 '19 at 01:55
  • @ymonad, make this an answer to this question please!!!! This is the best answer! I'd post it, but I don't want to take credit. – CryptoFool Mar 26 '19 at 02:04
  • Since other stackoverflower's are posting good answers. so just vote or approve them. – ymonad Mar 26 '19 at 02:07
  • But yours is better. The one upvoted is misleading, since it implies that \__nonzero__ has anything to do with this particular case, which it doesn't. – CryptoFool Mar 26 '19 at 02:08
  • Thanks @ymonad! The doc answered the question. – Alvin C Mar 26 '19 at 02:14
  • I kinda/sorta already knew the answer to this, but it was good to get a refresh by reading that documentation. Looking at it, I noticed something interesting that I'm now going to try hard to remember, as I could see it being important in some cases: **(Important exception: the Boolean operations or and and always return one of their operands.)** – CryptoFool Mar 26 '19 at 02:28

5 Answers5

2

Experiment time!

class Falsy:
    def __nonzero__(self):
        print("it's __nonzero__")
        return False
    def __len__(self):
        print("it's __len__")
        return 0
    def __bool__(self):
        print("it's __bool__")
        return False
    def __eq__(self, other):
        print("it's __eq__")
        return False

if Falsy():
    pass

# => it's __bool__

You can experiment with removing the methods to confirm which priority they are tested in (__bool__, then __len__, for Python 3).

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • This would be a useful answer if you also showed the list’s `__dict__` so you can see which methods exist. – AJNeufeld Mar 26 '19 at 02:08
  • How about showing this actually applied to the question, including the output you'd get? – CryptoFool Mar 26 '19 at 02:13
  • @Steve: The output is included. – Amadan Mar 26 '19 at 02:43
  • @Amadan, I see what you're doing now. Sorry. I misread what you were doing, and the commented output threw me off. Thought that was part of the code. I took off my -1. I don't think this really answers the question though, as the question involved what methods exist and get called on an empty array. Falsy is not an empty array. An empty array won't have a \__bool__ method. It WILL have a \__len__ method, which is what in the end determines why it is considered "False", because its length is 0. – CryptoFool Mar 26 '19 at 05:18
  • @Amadan, what your answer shows, which is cool, is which method is called first in the case where an object has all of the possible methods that could determine True/Falseness. - \__bool__ wins! You've shown that. But again, an empty array won't have a \__bool__ method. – CryptoFool Mar 26 '19 at 05:20
2

@ymonad gives the best answer in the question's comments, by simply referring to this doc:

https://docs.python.org/3/library/stdtypes.html#truth-value-testing

I don't want credit for this. I just can't handle it when the best answer isn't even an answer. If one can simply point to documentation, that will just about always be the best answer.

...grrrr...hey @ymonad, can I pass you a bounty or something, lol?

CryptoFool
  • 21,719
  • 5
  • 26
  • 44
0

From the documentation https://docs.python.org/2/reference/datamodel.html#object.nonzero:

object.__nonzero__(self)

Called to implement truth value testing and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __nonzero__(), all its instances are considered true.

And for Python 3 https://docs.python.org/3.7/reference/datamodel.html#object.nonzero:

object.__bool__(self)

Called to implement truth value testing and the built-in operation bool(); should return False or True. When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __bool__(), all its instances are considered true.

Try:

class MyList(list):
    def __bool__(self):
        return True


print(bool(list([])))
if list([]):
    print('This does not print')


print(bool(MyList([])))
if MyList([]):
    print('This prints')
Grismar
  • 27,561
  • 4
  • 31
  • 54
  • This answer contains the truth, but it really has nothing to do with \__bool__ in this case, so it's more complicated than it needs to be. @ymonad gives the best answer in the question's comments, by simply referring to this doc: https://docs.python.org/3/library/stdtypes.html#truth-value-testing – CryptoFool Mar 26 '19 at 02:08
0

Consulting the C-Python API documentation for PyList ...

https://docs.python.org/3.7/c-api/list.html

... we can see there is no list-specific “as bool” function. The only thing which can return the “truth” value is PyList_Size(PyObject *list), so the answer must be a.__len__() is used.

Disclaimer: At least, for CPython.

AJNeufeld
  • 8,526
  • 1
  • 25
  • 44
-1

You may want to refer to this answer.

I am not sure what you mean. If I assume you are looking for a Java's .equals() equivalent, I am going to say, there is no such thing in python.

An empty list is always False in python.

Edward Aung
  • 3,014
  • 1
  • 12
  • 15