.. index:: single: boolean; interpretation as .. _Arbitrary-Types-Bool: Arbitrary Types Treated As Boolean ================================== The following section would merely be an advanced topic, except for the fact that many common mistakes have their meaning changed and obscured by the Boolean syntax discussed. You have seen how many kinds of objects can be converted to other types. *Any* object can be converted to Boolean (type bool). *Read* the examples shown in this Shell sequence:: >>> bool(2) True >>> bool(-3.1) True >>> bool(0) False >>> bool(0.0) False >>> bool(None) False >>> bool('') False >>> bool('0') True >>> bool('False') True >>> bool([]) False >>> bool([0]) True The result looks pretty strange, but there is a fairly short general explanation: Almost everything is converted to ``True``. The only values among built-in types that are interpreted as False are - The Boolean value ``False`` itself - Any numerical value equal to 0 (0, 0.0 but not 2 or -3.1) - The special value ``None`` - Any empty sequence or collection, including the empty string (``''``, but not ``'0'`` or ``'hi'`` or ``'False')`` and the including empty list (``[]``, but not ``[1,2, 3]`` or ``[0]``) A possibly useful consequence occurs in the fairly common situation where something needs to be done with a list only if it is nonempty. In this case the explicit syntax:: if len(aList) > 0: doSomethingWith(aList) can be written with the more succinct Pythonic idiom :: if aList: doSomethingWith(aList) This automatic conversion can also lead to extra trouble! Suppose you prompt the user for the answer to a yes/no question, and want to accept 'y' or 'yes' as indicating True. You might write the following *incorrect* code. *Read* it:: ans = input('Is this OK? ') if ans == 'y' or 'yes': print('Yes, it is OK') The problem is that there are two binary operations here: ``==``, ``or``. Comparison operations all have higher precedence than the logical operations ``or``, ``and``, and ``not``. The ``if`` condition above can be rewritten equivalently with parentheses. *Read* and consider:: (ans == 'y') or 'yes' Other programming languages have the advantage of stopping with an error at such an expression, since a string like ``'yes'`` is not of type bool. Python, however, accepts the expression, and treats ``'yes'`` as ``True``. To test, *run* the example program ``boolConfusion.py``, shown below: .. literalinclude:: ../examples/boolConfusion.py :lines: 3- Python detects no error. The ``or`` expression is treated as ``True``, since ``'yes'`` is a non-empty sequence, interpreted as ``True``. The intention of someone writing :: if ans == 'y' or 'yes': presumably was that the condition meant something like :: (ans == 'y') or (ans == 'yes') This version also translates directly to other languages. Another correct Pythonic alternative that groups the alternate values together is :: ans in ['y', 'yes'] which reads pretty much like English. Be careful to use a correct expression when you want to specify a condition like this. .. index:: single: and; non-boolean operands single: or; non-boolean operands Things get even stranger! Enter these conditions themselves, one at a time, directly into the *Shell*:: 'y' == 'y' or 'yes' 'no' == 'y' or 'yes' 'y' == 'y' and 'yes' 'no' == 'y' and 'yes' 'no' or 'yes' 'no' and 'yes' The meaning of ``(a or b)`` and of ``(a and b)`` are exactly as discussed so far *if* each of the operands ``a`` and ``b`` are *actually* Boolean, but more elaborate definitions are needed if an operand is not Boolean:: val = a or b means :: if bool(a): val = a else: val = b and in a similar vein:: val = a and b means :: if bool(a): val = b else: val = a This strange syntax was included in Python to allow code like in the following example program ``orNotBoolean.py``. *Read* and test if you like: .. literalinclude:: ../examples/orNotBoolean.py :lines: 3- which sets ``color`` to the value of ``defaultColor`` if the user enters an empty string. Again, this may be useful to experienced programmers, bhe syntax can certainly cause difficult bugs, particularly for beginners! The ``not`` operator always produces a result of type bool.