Search code examples
pythonpython-3.xif-statementtruthiness

Difference between an if statement and an if equals statement


Is there an actual difference between

if statement:

and

if statement == True:

Aside from the first one being shorter, does one have a higher precedence, or is one slower?

EDIT:

I realized this may not have been clear, but statement is usually statement = True.


Solution

  • Those are not equal. Python allows you to define if statements over a large range of elements. You can for instance write:

    if []: # is False
        pass
    if 1425: # is True
        pass
    if None: # is False
        pass
    

    Basically if you write if <expr>, Python will evaluate the truthness of the expression. This is predefined for numbers (int, float, complex, not being equal to zero), some builtin collections (list, dict, not being empty), and you can define a __bool__ or __len__ on an arbitrary object yourself. You can get the truthness of an object by calling bool(..) on it. For example bool([]) == False.

    Example where if x is not equal to if x == True:

    For instance:

    if 0.1:
        pass # will take this branch
    else:
        pass
    

    will take the if branch, whereas:

    if 0.1 == True:
        pass
    else:
        pass # will take this branch
    

    will not take the if branch. This is because a number is equal to True if it is one (1, 1L, 1+0j,...). Whereas bool(x) for a number is True if x is non-zero.

    It is also possible to define an object where == will raise an exception. Like:

    class Foo:
    
        def __eq__(self,other):
            raise Exception()
    

    Now calling Foo() == True will result in:

    >>> Foo() == True
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in __eq__
    Exception
    

    It is however not advisable to raise exceptions in the __eq__ function (well I strongly advice against it anyway).

    It however holds that: if <expr>: is equivalent to if bool(<expr>):.

    Given the two are equal, evidently the <expr> == True will be slower since you do an extra call to __eq__, etc.

    Furthermore it is usually more idiomatic to check if a collection is empty with:

    some_list = []
    
    if some_list: # check if the list is empty
        pass
    

    This is also more safe since if it possible that some_list is None (or another kind of collection), you still check whether it holds at least one element, so changing your mind a bit will not have dramatic impact.

    So if you have to write if x == True, there is usually something weird with the truthness of the x itself.

    Some background on truthness:

    As is specified in the documentation (Python-2.x/Python-3.x). There is a way to resolve truthness.

    In , it is evaluated like (over-simplified version, more "pseudo Python" code to explain how it works):

    # Oversimplified (and strictly speaking wrong) to demonstrate bool(..)
    # Only to show what happens "behind the curtains"
    def bool(x):
        if x is False or x is None:
            return False
        if x == 0 or x == 0.0 or x == 0L or x == 0j:
            return False
        if x is () or x == [] or x == '' or x == {}:
            return False
        if hasattr(x,'__nonzero__'):
            y = x.__nonzero__()
            return y != 0 and y != False
        if hasattr(x,'__len__'):
            return x.__len__() != 0
        return True
    

    and an over-simplified version for :

    # Oversimplified (and strictly speaking wrong) to demonstrate bool(..)
    # Only to show what happens "behind the curtains"
    def bool(x):
        if x is False or x is None:
            return False
        if x == 0 or x == 0.0 or x == 0j:
            return False
        if x is () or x == [] or x == '' or x == {}:
            return False
        if hasattr(x,'__bool__'):
            return x.__bool__() is True
        if hasattr(x,'__len__'):
            return x.__len__() != 0
        return True