1

There is a possibility that I am searching under wrong keywords, but I can't find the answer to the question:

Is there a nice one-liner to provide a default value if the variable is NoneType?

For example:

def validate_quantity(self, value):
        instance = self.instance
        diff = value - instance.quantity

results in error:

unsupported operand type(s) for -: 'decimal.Decimal' and 'NoneType'

I know dictionaries have a .get() method which works like that:

smth.get('quantity', 200)

but it cannot be applied to an object instance.

This:

diff = value - (instance.quantity or 0)

does not work either because it returns 0 when instance.quantity is None, but also when it is [] or "".

user3840170
  • 26,597
  • 4
  • 30
  • 62
skelaw
  • 199
  • 4
  • 16
  • This doesn't make a great deal of sense. If instance.quantity is either [] or "" then surely you would want some kind of default or, even better, raise an exception because instance.quantity is expected to be Decimal. If it's a list or a string then something's gone terribly wrong – DarkKnight Mar 02 '23 at 07:23
  • 1
    This is just an example. The asker is looking for a general solution. – user3840170 Mar 02 '23 at 08:49
  • @user3840170 The question is very specific around NoneType – DarkKnight Mar 02 '23 at 08:51

2 Answers2

2

Using the walrus operator, introduced in Python 3.8 (PEP 572):

diff = value - (0 if (q := instance.quantity) is None else q)

To me, it looks at best moderately readable (you can also try swapping ‘then’ and ‘else’ parts, i.e. q if (q := instance.quantity) is not None else 0, if you prefer), but it has the advantage that it only evaluates instance.quantity once, and does not evaluate the fallback expression if not needed.

There have been proposals to introduce a proper None-coalescing operator (see PEP 505), but there is currently no consensus to add one to the language. The LWN article ‘Not coalescing around None-aware’ covers some discussions.

user3840170
  • 26,597
  • 4
  • 30
  • 62
  • Isn't this functionally equivalent to *diff = value - (0 if instance.quantity is None else instance.quantity)* ? And, if so, what is the benefit of the assignment expression? – DarkKnight Mar 02 '23 at 08:47
  • @Pingu Read the answer again. – user3840170 Mar 02 '23 at 08:48
  • I read it. So you're saying that the evaluation of instance.quantity is potentially more expensive than the instantiation of *q*. I guess that's your point. Fair enough – DarkKnight Mar 02 '23 at 08:50
0

How about:

diff = value - (instance.quantity if not isinstance(instance.quantity, type(None)) else Decimal(1000))

...where Decimal(1000) is your default value and the isinstance() test is specific for NoneType (as per the question)

DarkKnight
  • 19,739
  • 3
  • 6
  • 22