vac
vac

Reputation: 723

How to throw exception when comparing with None on Python 2.7?

In Python 2.7:

Expression 1 (fine):

>>> 2 * None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

Expression 2 (fine):

>>> None is None
True

Expression 3 (bad):

>>> 2 < None
False

Expression 4 (bad):

>>> None<None
False

Expression 5 (bad):

>>> None==None
True

I want to somehow force expressions 3, 4 and 5 to throw TypeError (same as in expression 1).

Python 3.4 is nearly there - only expression 5 returns True.

I need it in 2.7.


My use case (if someone interested):

I'v made application that evaluates some expressions (example):

d = a+b
e = int(a>b)
f = a if a<b else b if b<c else c

Expressions are based on values (a, b and c) which comes from deserialized json. Most of the time values (a, b and c) are integers, but sometimes (when value is missing) it is None. When value is missing and is used in some expressions then expression should return None (I was thinking about catching TypeError exception).

In case when a=None, b=1, c=2, exptected result is: d=None, e=None, f=None.

In case when a=1, b=2, c=None, expected result is: d=3, e=0, f=1

Upvotes: 2

Views: 285

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180441

You can use issinstance:

from numbers import Number


def pre(a, b, c):
    if not isinstance(a, Number) or not isinstance(b, Number):
        return None, None, None
    if not isinstance(c, Number):
        return a + b, a > b, a if a < b else b
    return a + b, a > b,  a if a < b else b if b < c else c

If any number in a calculation is None you return all Nones, if c is None you return your calculations excluding the if b < c else c and if they are all numbers then return all the expressions:

In [53]: pre(None,1,2)
Out[53]: (None, None, None)

In [54]: pre(1,2,None)
Out[54]: (3, False, 1)

In [55]: pre(None,None,None)
Out[55]: (None, None, None)

In [56]: pre(3,4,5)
Out[56]: (7, False, 3)

Upvotes: 0

Claudiu
Claudiu

Reputation: 229391

You can't change the behavior of None. However, you can implement your own type which has the behavior you want. As a starting point:

class CalcNum(object):
    def __init__(self, value):
        self.value = value

    def __add__(self, o):
        return CalcNum(self.value + o.value)

    def __lt__(self, o):
        if self.value is None or o.value is None:
            # Pick one:
            # return CalcNum(None)
            raise TypeError("Can't compare Nones")

        return CalcNum(self.value < o.value)

Upvotes: 1

Related Questions