Search code examples
pythontuplesnonetypecomparison-operators

Should I just use `==` to compare to `(None, None)` tuple?


I have a function, which can return either a tuple of two ints or a tuple of (None, None):

(for the purposes of this question, let's assume that this return format is the only way to do this, and it cannot be changed)

from typing import Tuple, Union

def foo(n: int) -> Union[Tuple[int, int], Tuple[None, None]]:
    if n < 0:
        return None, None
    return n, n

Then I want to write a pytest unittest to test this function. It's always said that one should compare to None with is, but this obviously doesn't work:

def test_foo():
    assert foo(1) == (1, 1)
    assert foo(-1) is (None, None)  # fails obviously!

Should I in this situation just use == to compare the result?

def test_foo():
    assert foo(1) == (1, 1)
    assert foo(-1) == (None, None)  # best way?

Solution

  • You should use ==, but indeed it's not "obvious" that using is would fail.

    For example

    def foo():
        return (1, 2)
    
    print(foo() is foo())
    

    MAY actually return True (it does in CPython, not sure about other implementations).

    Tuples are NOT to be considered entities, but values. Identity on values shouldn't be used as it may match or not (like happens for example for strings or numbers).

    If in the code above you use [1, 2] instead of (1, 2) then it's guaranteed that is will return False because lists are entities, not values, and identity can be used in predictable ways.