My elif conditional branching isn’t working!! [Python]

Contents
  1. The problematic program
  2. How to fix it
  3. Addendum (August 2022)

This article was automatically translated from Japanese using AI. The Japanese version is the authoritative version.

Have you ever wanted to branch on multiple conditions with an if statement, tried using elif, and found that although no error was raised the results still weren’t right?
If so, the situation described below might be what’s happening.
I made this mistake myself, so I’m writing it down here for reference.

The problematic program

The problem arises when you write two conditions in the if and elif statements of a program that includes elif.

def trable(a, b):
    if a >= 10 & b >= 10:
        print("patern A")
    elif a >= 10 & b < 10:
        print("patern B")
    elif a < 10 & b >= 10:
        print("patern C")
    else:
        print("patern D")

trable(11, 11)
trable(11, 9)
trable(9, 11)
trable(9, 9)

When you run the program above, you might expect the cases to be sorted into patterns A, B, C, and D in order from the top, but what you actually get is the output below.

patern A
patern B
patern C
patern B

So what happens if we swap the order?

def trable(a, b):
    if a >= 10 & b >= 10:
        print("patern A")
    elif a < 10 & b < 10:
        print("patern B")
    elif a >= 10 & b >= 10:
        print("patern C")
    else:
        print("patern D")

trable(11, 11)
trable(9, 11)
trable(11, 9)
trable(9, 9)

If you swap the code for patterns B and C, expecting the output to come out as A, B, C, D, what you actually get is the output below.

patern A
patern D
patern D
patern D

elif itself is used as follows when you want to define multiple conditions.

if 条件式A:
  条件式Aが真(True)となった場合の処理
elif 条件式B:
  条件式Aが偽(False)で、条件式Bが真(True)となった場合の処理
else:
  条件式Aが偽(False)で、条件式Bも偽(False)となった場合の処理

However, once the conditional expressions in the if and elif statements contain two conditions, the problem described above is likely to occur.
As a result, you don’t get the output you intended.

The tricky part is that no error is raised, so you can’t tell whether things are working until you actually look at the results.

How to fix it

When you want to branch into multiple cases using compound conditions, avoid specifying multiple conditions in the elif statement.

def resolve(a, b):
    if a>= 10:
        if b >= 10:
            print("patern A")
        else:
            print("patern B")

    else:
        if b >= 10:
            print("patern C")
        else:
            print("patern D")

resolve(11, 11)
resolve(11, 9)
resolve(9, 11)
resolve(9, 9)

It’s more cumbersome, but doing it this way gives you exactly the output you expect.

Programming has unexpected pitfalls like this, so it’s a good lesson in carefully checking the code you write.

Addendum (August 2022)

It turns out the problem was that I hadn’t wrapped the conditions in parentheses.

def trable(a, b):
    if (a >= 10) & (b >= 10):
        print("patern A")
    elif (a < 10) & (b < 10):
        print("patern B")
    elif (a >= 10) & (b >= 10):
        print("patern C")
    else:
        print("patern D")

With this change, the branching worked correctly.
Alternatively, you can also fix it by writing and instead of &.

def trable(a, b):
    if a >= 10 and b >= 10:
        print("patern A")
    elif a < 10 and b < 10:
        print("patern B")
    elif a >= 10 and b >= 10:
        print("patern C")
    else:
        print("patern D")

& and and may seem equivalent, but & also acts as a bitwise AND, so in the original program

a >= 10 & b < 10

this apparently means a >= (10 & b) < 10, and
with a=9, b=9 the inequality becomes
9>=8<10, which evaluates to True.

Tricky stuff…

Previous
Next