0

I cannot use the following statement because x and y may be defined as None:

if x*y > 9:
    pass

unsupported operand type(s) for *: 'NoneType' and 'NoneType'

So I should check first for the existence:

if x and y:
    if x*y > 9:
        pass

It seems a bit redundant. Is there a better way to achieve this?

isar
  • 1,661
  • 1
  • 20
  • 39
  • Do you mean `x` and `y` may not be defined at all or that they may be defined as `None` rather than as float/ints/Booleans? You seem to ask about the first but the error is about the second. – Rory Daulton Jul 08 '17 at 00:29
  • a try/except is needed if x or y doesn't exist at all – PRMoureu Jul 08 '17 at 00:30
  • @RoryDaulton I updated my question, thanks. They may be defined as `None`. – isar Jul 08 '17 at 00:37
  • It does not really make a difference here, but in general I would check for `x is None` instead of just `x`, as `x` might be zero (also, you make more explicit what the check is for) – Andrea Corbellini Jul 08 '17 at 00:45

3 Answers3

3

You can do:

if x and y and x*y > 9:
    pass

If you get even more checks it might be more comfortable to use all:

if all([
    x,
    y,
    x*y > 9,
    other conditions,...]):
    pass
Johannes
  • 3,300
  • 2
  • 20
  • 35
  • 4
    `all` solution does not work because `x*y > 9` will be evaluated whiling making the list. – falsetru Jul 08 '17 at 00:30
  • Yea you are right. `all` does short-circuit, but the list creation is the problem. I wonder if there is a pretty solution...? – Johannes Jul 08 '17 at 00:32
3

Following the EAFP (Easier to Ask Forgiveness than Permission) protocol, here's an alternative using try and except:

try:
   if x * y > 9:
       pass
except TypeError:
   pass
cs95
  • 379,657
  • 97
  • 704
  • 746
2

While if x and y and x * y > 9: is the most straightforward way, an alternative I find satisfying in an hard to define way is to use defaults for x and y when they're falsy:

if (x or 0) * (y or 0) > 9:

Since replacing either value with 0 makes the result 0, the test doesn't pass, as expected, when either value is None. This works because Python boolean and and or don't return True or False they return the last value evaluated (which will be truthy or falsy already). So if x is a non-zero number, you use x, otherwise you use 0, and same goes for y.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271