3

I have 2 variables, say x and y, and I need to check which of them is None

if x is None and y is None:
    # code here
else:
    if x is not None and y is not None:
        # code here
    else:
        if x is None:
            # code here
        if y is None:
            # code here

Is there a better approach to do this?
I am looking for a shorter IF ELSE structure.

yash
  • 1,357
  • 2
  • 23
  • 34
  • Also, note that null does not exist in python. For more information refer to https://stackoverflow.com/questions/3289601/null-object-in-python – yash Oct 23 '17 at 14:44

7 Answers7

3

Keeping the order you used:

if x is None and y is None:
    # code here for x = None = y
elif x is not None and y is not None:
    # code here for x != None != y
elif x is None:
    # code here for x = None != y
else:
    # code here for x != None = y

Modifying the order to reduce boolean evaluations:

if x is None and y is None:
    # code here for x = None = y
elif x is None:
    # code here for x = None != y
elif y is None:
    # code here for x != None = y
else:
    # code here for x != None != y

In a 4 case scenario, you should consider which of the options has a higher probability and which has the second higher and keep them the first two options, as this will reduce the amount of conditions checked during execution. The last two options will both execute the 3 conditions so the order of these two doesn't matter. For example the first code above considers that prob(x=None & y=None) > prob(x!=None & y!=None) > prob(x=None & y!=None) ~ prob(x!=None & y=None) while the second one considers that prob(x=None & y=None) > prob(x=None & y!=None) > prob(x!=None & y=None) ~ prob(x!=None & y!=None)

Adirio
  • 5,040
  • 1
  • 14
  • 26
0
  def func1(a):
    print a
  def func2(a):
    print a
  def func3(a):
    print a
  def func4(a):
    print a

  options = {(1, 1): func1,
                (1, 0): func2,
                (0, 1): func3,
                (0, 0): func4,}

  options[(True, True)](100)

output:

100
galaxyan
  • 5,944
  • 2
  • 19
  • 43
  • That requires signatures to be equal for all functions inside – Adirio Oct 23 '17 at 14:23
  • @Adirio no it is not. it can be changed to *args – galaxyan Oct 23 '17 at 14:24
  • The problem is not while defining the function, the problem is when you call it. You passed `100` before knowing which function would be called, so all of them require to handle 1 argument (even if they are not doing anything with it. Basically you would need to take the argument sets of each function and take the union of all of them to get the calling signature. Same for the output. – Adirio Oct 23 '17 at 14:30
  • @Adirio it is just an example. you can pass any args to function as you want by changing function definition. Python does not limit you on that side – galaxyan Oct 23 '17 at 14:34
  • @galaxyan But what if `func1` requires parameters `"foo", 1` and `func2` requires parameter `False`? How would you write the `options[(x, y)](...)` line? You could use `lambda` or `partial` but that won't make the code any simpler. – tobias_k Oct 23 '17 at 15:12
  • @Adirio if you define the function as func(*args), you can pass anything to the function. I am not sure whether or not you understand *args and **kwargs – galaxyan Oct 23 '17 at 15:16
  • @galaxyan I do know how `*args` and `**kwargs` work, Im talking about the function **call**. You call it with `(100)` in your example. Imagine that the first option requires as parameters a list of tuples, the second a callable and a tuple with arguments as callback, the third nothing and the forth a specific object. Then you need to call the function with the list of tuples, the callable, the tuple with arguments and the object; and determine inside the function which are usful and which not. If the signature is the same it is simple, but it gets complicated fast with different signatures. – Adirio Oct 23 '17 at 15:33
  • @Adirio If it becomes very complex, so does the your if statements. – galaxyan Oct 23 '17 at 15:37
  • The complexity of an `if ... elif ... else ...` statement comes from the conditions while the `dict` of callables comes from the inner signatures, both for inputs and outputs. The two are valid approaches, I use this kind of approach when the signatures are similar. – Adirio Oct 24 '17 at 06:47
0

If you need 4 different paths for each of the possible combination of x and y, you can't really simplify it that much. That said, I would group the checks for one of the variables (i.e. check if x is None first, then inside, check if y is None.)

Something like this:

if x is None:
    if y is None:
        # x is None, y is None
    else:
        # x is None, y is not None
else:
    if y is None:
        # x is not None, y is None
    else:
        # x is not None, y is not None
tyteen4a03
  • 1,812
  • 24
  • 45
0

you can start by using the elif statement, it will be a little bit shorter just like this:

if x is None and y is None:
    # code here
elif x is not None and y is not None:
    # code here
elif x is None:
    # code here
if y is None:
    # code here`
Rayane Bouslimi
  • 193
  • 1
  • 1
  • 9
0

If you have two booleans, there are four distinct possibilities: 00 01 10 and 11. If in each case something distinctly different is supposed to happen, there is not really something that could reduce the number of tests.

Having said that, in some comparable cases pattern matching might feel more straightforward. I don't know about that in Python though.

MrMeeSeeks
  • 91
  • 8
0

Assuming you need to have all 4 cases covered seperately:

if not x and not y:
    # code here (both are none or 0)
elif not x
    # code here (x is none or 0)
elif not y
    # code here (y is none or 0)
else
    #code here (both x and y have values)

This would be the shortest way to handle it, but doesn't only check for None/Null values. not x returns true for anything falsey, such as empty strings, False, or 0.

ividito
  • 321
  • 3
  • 14
  • 1
    Note that `not (False)` is True. – tyteen4a03 Oct 23 '17 at 13:36
  • This is true, see https://stackoverflow.com/questions/20420934/python-booleans-if-x-vs-if-x-true-vs-if-x-is-true for details on how `if x:` stuff gets handled in Python. – ividito Oct 23 '17 at 13:38
  • 1
    No, what I am saying is that the original code only asks for `None` checking, whereas your code will let anything falsey pass. – tyteen4a03 Oct 23 '17 at 13:40
-1

The below logic should run for all the combination. Write in your language

 if (x is not null and y is not null){
        //code here
    }
 else if(x is null and y is not null){
        //code here
    }
 else if(x is not null and y is null){
        //code here
    }
 else
    {
    //Code here
    }

The C Code for the same:

int main()
{
    int x,y;
    printf("Enetr Two Number");
    scanf("%d%d",&x,&y);

        if(x!=NULL && y!=NULL)

            printf("X and Y are not null");
            else if(x==NULL && y!=NULL)
            printf("X is null and Y is not null");
            else if(x!=NULL && y==NULL)
            printf("X is not null and Y is null");

    else
    {
        printf("The value of x and y are null");
    }
}
Neeraj Kumar
  • 771
  • 2
  • 16
  • 37