# How to make the match statement work?

Trying to learn Python 3.10 pattern matching. Tried this example after reading 8.6.4.9. Mapping Patterns

``````    >>> match 0.0:
...  case int(0|1):
...   print(1)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: called match pattern must be a type
>>>
``````

Especially the note on built-in types, including int. How should I code to test for an integer value of 0 or 1 (the example in the doc) and not get this error?

Hello Gerald,

the match pattern is here â0.0â - but <.> this little point makes a float
out of this pattern ?! You cannot use then âintâ for to check this pattern ?
I have to re-think a while âŚ this answer only as hint to you at first.

Hi Gerald,

You should read the tutorial:

and remember that match statements are overpowered if youâre just trying
to match a simple value. For that you should probably stick to a simple
ifâŚelifâŚ chain.

``````if x == 0:
...
``````

But as a learning exercise, try this:

``````num = 0.0
match num:
case int(n) if n in (0, 1):
print(f"matched int {n}")
case float(n) if n in (0, 1):
print(f"matched float {n}")
``````

which will print âmatched float 0.0â. We can combine the two tests:

``````match num:
case int(n) | float(n) if n in (0, 1):
print(f"matched int or float {n}")
``````

As you can see, `if num in (0, 1)` is much simpler if that is all you
are doing. Using a match statement for this is like using a nuclear
powered bulldozer to crack a peanut.

The above translates to something roughly like this, using the walrus
operator:

``````if isinstance(n := num, int) or isinstance(n := num, float):
if n in (0, 1):
print(...)``````
1 Like

Well, yes it is overpowered for the simple test but Iâm not trying to solve a IRL code problem, Iâm trying to learn by moving from simple to complex. Simplest for me is all constants.

``````>>> match 1:
...  case 1:
...   print ('one')
...
one
>>>
``````

cool, next I wanted to match by type:

The doc says I can do this:

class_pattern ::= name_or_attr â(â [pattern_arguments â,â?] â)â

but, apparently not, even though built-in types are explicitly mentioned just below:

``````>>> match 'str':
...  case str():
...   print('str')
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: called match pattern must be a type
>>>
``````

So, I am confused. The tutorial doesnât seem to address this kind of thing.

then copying the example on the linked page:

`int(0|1)` matches the value `0`

leads to the error I posted. Now, super confused.

You can match with type.

``````your_number = 5
match your_number:
case number if type(your_number) is int:
print(number)
``````

Hi Gerald,

have you been shadowing the names of built-in types like `int` and `str` with your own objects?

``````>>> match 0.0:
...     case int(0|1):
...         print(1)
...
>>> int = "something other than the builtin 'int'"
>>> match 0.0:
...     case int(0|1):
...         print(1)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: called match pattern must be a type
>>>
``````

It looks like the error messages should be improved. And watch out for
the gotcha!

First, here is the gotcha to watch out for. Matching on a type like this
appears to work.

``````match 'this is a string':
case str:
print("matched!")
``````

prints âmatched!â as you expect. But what weâve actually done is
not match on the type `str`, but matched the pattern âstrâ, which
represents a name. So it binds the matched values to the pattern, and we
get:

``````print(str)
# prints 'this is a string', not <class 'str'>
``````

Gotcha!

So run `del str` to get rid of that pesky variable shadowing the
built-in str type, and letâs match it properly.

``````del str
match 'this is a string':
case str():
print("matched!")
``````

When matching against a type, you need parentheses after the type,
otherwise youâre just matching against a name, which is equivalent to
doing `str = 'this is a string'`.

Now we can improve it by matching against the type and binding to a name
in the same test, which then lets us refer to the name that we used:

``````match 'this is a string':
case str(s):
print(f"matched the string {s!r}")
``````

We can add a guard clause:

``````match 'this is a string':
case str(s) if s.islower():
print(f"matched the lowercase string {s!r}")
``````

Remember, matchâŚcase is not like a switch statement. Its a disguised
assignment!

@tjol maybe, see below
@steven.daprano Are you saying that when I write:

``````>>> match int(1):
...  case str:
...   print(1)
...
1
>>>
``````

âcase strâ matches everything and assigns it to the name âstrâ? That would explain my what Iâm seeing and also explain my top post, since I had earlier, incorrectly written âcase intâ which effectively shadowed the int builtin function as @tjol asked

And this would indeed be a big âgotcha!â

It would be nice to see simple type matching covered in the tutorial. Annd, the doc page I linked talks about type matching but doesnât have simple, complete examples which makes it harder for me to figure out what I can and cannot do.

Hi Gerald,

Yes, thatâs exactly what Iâm saying!

Its an easy mistake to make. I can see this becoming a gotcha for Python
programmers, but new and experienced, for decades to come.