Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edit boolean and operator

So I've been messing around with the standard operators in classes to try and see what i can make, but i haven't been able to find how to edit the boolean and operator.

I can edit the bitwise &operator by defining __and__(self), but not the way that and behaves. Does anyone know how I can change the behavior of a and b where a and bare instances of the class I'm making?

Thanks in advance!

like image 212
Dennis Avatar asked Dec 22 '17 12:12

Dennis


2 Answers

In Python 2, and and or access __nonzero__:

>>> class Test(object):
...     def __nonzero__(self):
...         print '__nonzero__ called'
...         return True
... 
>>> Test() and 1
__nonzero__ called
1

In Python 3, __nonzero__ has been renamed to __bool__.

>>> class Test:
...     def __bool__(self):
...         print('__bool__ called')
...         return True
... 
>>> Test() and 1
__bool__ called
1

Note that short-circuit evaluation might suppress a call to __nonzero__ or __bool__.

>>> 0 and Test()
0
>>> 1 or Test()
1

Another speciality to be aware of is that Python is trying to access __len__ if __nonzero__ / __bool__ is not defined and treats the object as truthy if __len__ returns a value other than 0. If both methods are defined, __nonzero__ / __bool__ wins.

>>> class Test:
...     def __len__(self):
...         return 23
... 
>>> Test() and True
True
>>>
>>> class Test:
...     def __len__(self):
...         return 23
...     def __bool__(self):
...         return False
... 
>>> Test() and True
<__main__.Test object at 0x7fc18b5e26d8> # evaluation stops at Test() because the object is falsy
>>> bool(Test())
False

Is there any way i can have this return something other than a bool, like, say, a list of bools?

Unfortunately, no. The documentation states that the method should return False or True but in fact you get a TypeError if you let it return something else.

>>> class Test:
...     def __bool__(self):
...         return 1
... 
>>> Test() and 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __bool__ should return bool, returned int
>>> 
>>> bool(Test())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __bool__ should return bool, returned int
like image 82
timgeb Avatar answered Sep 20 '22 11:09

timgeb


The and operator converts the first operands to boolean using __bool__, and then does a predefined action to the booleans (if first.__bool__() is True, return second, else return first). There is no way to change this behavior.

like image 39
internet_user Avatar answered Sep 17 '22 11:09

internet_user