 # Python 3.10: cyclomatic complexity of match-case syntax

I am wondering about the cyclomatic complexity of using the new match-case syntax in Python 3.10, and later. What is the cyclomatic complexity difference (if any?) of a match-case code as opposed to code that uses the if-elif-else syntax?

So my question is this: Are there any benefits in using the match-case syntax in terms of cyclomatic complexity?

1 Like

Benefits in terms of cyclomatic complexity alone? I doubt it.

Cyclomatic complexity measures only the number of independent paths
through a program, not how complex each path is. So both of these
program snippets have the same cyclomatic complexity:

``````# Snippet 1
if x == 1:
print("done")

# Snippet 2
import math
a = x + 4
b = a*20
c = math.sqrt(b)
d = c - 9
flag = int(isinstance(d, list))
e = -2345*flag
f = 3*d + e
if f == 3:
print("done")
``````

I expect that if you take a match statement, and re-write it in terms of
low-level if…else decision points, there would be the same number of
paths. The difference is that the match cases involve much higher-level
tests and so is a lot less verbose.

Consider:

``````match sequence:
case (1, 2, 99, x, 8, y, 0):
print(x + y)
``````

Which I think we could re-write as:

``````if instance(sequence, collections.abc.Sequence):
t1, t2, t3, x, t4, y, t5  = sequence
if t1 == 1:
if t2 == 2:
if t3 == 99:
if t4 == 8:
if t5 == 0:
print(x + y)
``````

So the match statement should be counted as the same cyclomatic
complexity as the chain of if statements, but the first version takes
three lines of code and the second eight and five temporary variables.

1 Like

@steven.daprano, now that Python 3.10 final version is out, I have tested the cyclomatic complexity of 2 functions: the 1st incorporates the `if-elif-else` syntax and the 2nd incorporates the `match-case` syntax.

1st functon (`if-elif-else` syntax):

``````def number_tester(number):
if number == 1:
print("Number is 1.")
elif number == 2:
print("Number is 2.")
else:
print("Number is unknown.")

number_tester(number=1)
``````

2nd function (`match-case` syntax)

``````def number_tester(number):
match number:
case 1:
print("Number is 1.")
case 2:
print("Number is 2.")
case _:
print("Number is unknown.")

number_tester(number=1)
``````

The 1st function has a cyclomatic complexity of 3 as reported by radon:

``````test.py
F 1:0 number_tester - A (3)

1 blocks (classes, functions, methods) analyzed.
Average complexity: A (3.0)
``````

And the 2nd function has a cyclomatic complexity of 1 as reported by radon:

``````test.py
F 1:0 number_tester - A (1)

1 blocks (classes, functions, methods) analyzed.
Average complexity: A (1.0)
``````

The command used to get the provided results was `radon cc "test.py" -a -s`.

So, as you can see, the `match-case` syntax in Python 3.10 does make a difference in terms of cyclomatic complexity of code, i.e., it reduces it.

It looks like `radon` doesn’t specify compatibility yet with Python 3.10, and it doesn’t look like it recognises match statements yet. That’s why it’s not producing anything.

Are we sure that radon knows how to correctly interpret match
statements? Has it been updated to analyse match statements?

If you were to translate the two Python functions into C, using
`if` for the first and translating the match statement to a C switch
statement, would you still insist that they have different cyclomatic
complexity?

The documentation for radon doesn’t mention match statements:

@steven.daprano, thanks for that link. Yes, radon devs apparently haven’t included the `match` statement yet.
I’m wondering whether they’ll treat `match` as `+0` and then each `case` statement as `+1`, or the `match` statement also as `+1`?