Search code examples
pythontruthiness

Truthiness test not performing as expected


I have a simple function that tests an item in a tuple to see if it is truthy or not. For some reason all tests come back True (...if connection:...), even though the value being tested is either a 1 (assumed True) or 0 (assumed false).

I tested to see if 1 == True (output: True), 1 == False (False), connection is True (False) just to try to understand what is going on.

User input: players = [('a', 1), ('b', 0)]

Function:

def validplayers(players):
    for player, connection in players:
        if connection:
            player
        print player, connection, 1 == True, 1 == False, connection is True

Output:

a 1 True False False
b 0 True False False

The connection var is passing a 1 or 0 which type(connection) defines as an int.


Solution

  • Your error is looking at connection is True. This is always going to be False. is tests for identity, two expressions resulting in a reference to the same object in memory.

    If you want to print the truth value of an object, use the bool() function:

    >>> bool(1)
    True
    >>> bool(0)
    False
    

    That 1 == True works at all is because in Python, the bool type is a subclass of int:

    >>> issubclass(bool, int)
    True
    

    The integer value of True is 1, and False has an integer value of 0. Testing for equality won't work for other integer values:

    >>> 1 == True
    True
    >>> 2 == True
    False
    >>> bool(2)
    True
    

    Note that your if test is otherwise meaningless; the only thing that is executed or not is the line player, which is a no-op expression that just returns the reference to player, but since there is nothing else there the reference is unused.

    If you wanted the print statement to be executed only when if is true, you need to indent it to be further to the right from if and make it part of the nested block:

    def validplayers(players):
        for player, connection in players:
            if connection:
                print player, connection, bool(connection)
    

    This then only prints something for player a:

    >>> def validplayers(players):
    ...     for player, connection in players:
    ...         if connection:
    ...             print player, connection, bool(connection)
    ...
    >>> validplayers([('a', 1), ('b', 0)])
    a 1 True