Python Forum
Why can't I explicitly call __bool__() on sequence type? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Why can't I explicitly call __bool__() on sequence type? (/thread-34578.html)

Pages: 1 2


Why can't I explicitly call __bool__() on sequence type? - quazirfan - Aug-10-2021

In this code, if foo: python will call foo.__bool__() implicitly to get the boolean value of foo. Which is why the following code segments work,
if 't': print("T") 
if [1]: print("T")
But I wanted to check if I can call the __bool__() method myself like the following;
't'.__bool__() # AttributeError: 'str' object has no attribute '__bool__'
[1].__bool__() # AttributeError: 'list' object has no attribute '__bool__'
As you can see it do not work, and in both cases I get AttributeError.

If __bool__() can be called implicitly in a if statement, why can I not call it explicitly?


RE: Why can't I explicitly call __bool__() on sequence type? - buran - Aug-10-2021

Both str and list don't have __bool__ defined and [I guess] they are evaluated in boolean context by using __len__

Quote: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.
>>> dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> 



RE: Why can't I explicitly call __bool__() on sequence type? - deanhystad - Aug-10-2021

I don't think str has a __bool__ method. I looked around for a while and I can't find it anywhere (as expected). I think bool() may have tests for some standard types (int, str, list, set...) built into the function and __bool__ is meant as a way to override the default assessment.


RE: Why can't I explicitly call __bool__() on sequence type? - quazirfan - Aug-10-2021

Thanks. That cleared it up.

(Aug-10-2021, 08:21 PM)buran Wrote: If a class defines neither __len__() nor __bool__(), all its instances are considered true.

Here if str: print("True") # True - I am passing the name of the class, not an instance, but it still works.

Why is that?


RE: Why can't I explicitly call __bool__() on sequence type? - buran - Aug-11-2021

you understand that each class is instance of class type, right?

>>> type(str)
<class 'type'>
>>> dir(type)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__weakrefoffset__', 'mro']
>>> 
Quote: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.

Also explained in more detail

Quote:Truth Value Testing

Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below.

By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object. Here are most of the built-in objects considered false:
  • constants defined to be false: None and False.
  • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • empty sequences and collections: '', (), [], {}, set(), range(0)

Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)



RE: Why can't I explicitly call __bool__() on sequence type? - quazirfan - Aug-11-2021

(Aug-11-2021, 04:09 AM)buran Wrote: you understand that each class is instance of class type, right?

No I didn't. Thanks! I am following a book that hasn't talked about it yet. As I am reading, I usually stop and experiment with the things I have learned, and hence the tsunami of questions.

Thanks for your answers so far!


RE: Why can't I explicitly call __bool__() on sequence type? - buran - Aug-11-2021

Check my updated answer, I added a link with some more details


RE: Why can't I explicitly call __bool__() on sequence type? - quazirfan - Aug-17-2021

(Aug-11-2021, 04:14 AM)buran Wrote: you understand that each class is instance of class type, right?

I come from Java background where every class implicitly inherits from object class. I was under the assumption it is the same with python. Then why type(str) do not return object?


RE: Why can't I explicitly call __bool__() on sequence type? - deanhystad - Aug-17-2021

Classes are definitions of types, so the type of a class is "type". But this has nothing to do with inheritance.
class A():
    pass

class B(A):
    pass

class C(B):
    pass

c = C()
print(type(c))
print(type(C))
print(C.__base__)
print(A.__base__)
Output:
<class '__main__.C'> <class 'type'> <class '__main__.B'> <class 'object'>
The type of the object "c" is the class "C". The type of the class "C" is type. The superclass, or base class of "C" is "B". Oh, and the base class of "A" is object.

Think of the type of an object as the the thing that defines how the object works. The type of "hello" is class str, because the class str defines what you can do with 'hello'. It knows how to do things like find() and upper(). The type of str is type, because str is a class, and type defines how classes work. Type knows how to get the base class of a class or get the mro (method resolution order).


RE: Why can't I explicitly call __bool__() on sequence type? - quazirfan - Aug-18-2021

@deanhystad Thanks, that cleared it up a bit.