Lists may contain an arbitrary number of elements. There is no way to individually match all of the elements in a list in a case.
You can match all of the elements and then put a guard on the case.
match mylist:
case [*all_elements] if 'hi' in all_elements:
...
This doesn't seem much better than:
if 'hi' in mylist:
...
But let's say you want to determine if list has 'hi' as the first element and includes it again?
match mylist:
case ['hi', *other_elements] if 'hi' in other_elements:
...
Answer from Chris on Stack OverflowVideos
Lists may contain an arbitrary number of elements. There is no way to individually match all of the elements in a list in a case.
You can match all of the elements and then put a guard on the case.
match mylist:
case [*all_elements] if 'hi' in all_elements:
...
This doesn't seem much better than:
if 'hi' in mylist:
...
But let's say you want to determine if list has 'hi' as the first element and includes it again?
match mylist:
case ['hi', *other_elements] if 'hi' in other_elements:
...
Using match/case is not the most appropriate way to determine if a list contains some particular value. However, to answer the question then:
mylist= ["hello", "hi", 123, True]
for element in mylist:
match element:
case 'hello':
print('hello detected')
case 'hi':
print('hi detected')
Is there a way to match a value against a list of values? I'm trying to do something like this without using a bunch of ifs, but I can't figure out how.
animal = 'dog'
match animal:
case ['dog', 'cat', 'pig']:
print('Mammal!')
case ['crocodile', 'turtle']:
print('Reptile!')
case _:
print('I dont know')cases accept a "guard" clause, which you can use for this purpose:
match x:
case w if w in a:
return "132"
case w if w in b:
return "564"
case w if w in c:
return "798"
the w here actually captures the value of x, part of the syntax here too, but it's more useful in some other fancy cases listed on the linked whatsnew page.
In this example, it's simpler to use good ol' if-elif.
if x in a:
return "132"
elif x in b:
return "564"
elif x in c:
return "798"
If you don't want to repeat the variable name, you can use a loop:
for lst, retval in [
(a, "132"),
(b, "564"),
(c, "798"),
]:
if x in lst:
return retval
Note: This is very similar to my answer on "Is there a way to match inequalities in Python ≥ 3.10?".
Now, it would be different if you were doing any actual structural pattern matching, which is what match-case is intended for. Then you might want to use a guard clause like in tevemadar's answer. Say for example x is a structure:
match x:
case (w,) if w in a:
return "132"
case (_, w) if w in b:
return "564"
case (_, _, w) if w in c:
return "798"
You can do this without match-case, but it's not as elegant:
for n, lst, retval in [
(1, a, "132"),
(2, b, "564"),
(3, c, "798"),
]:
if len(x) == n and x[-1] in lst:
return retval
Rather than match type(v), match v directly:
values = [
1,
"hello",
True,
]
for v in values:
match v:
case str():
print("It is a string!")
case bool():
print("It is a boolean!")
case int():
print("It is an integer!")
case _:
print(f"It is a {type(v)}!")
Note that I've swapped the order of bool() and int() here, so that True being an instance of int doesn't cause issues.
This is a class pattern match.
You can match directly against the type of v, but you need a value pattern to refer to the types to match, as a "dotless" name is a capture pattern that matches any value. For example,
import builtins
values = [
1,
"hello",
True
]
# Caveat: this will continue to work even if someone
# rebinds the built-in, but not, for example, if builtins.str
# itself is rebound.
for v in values:
match type(v):
case builtins.str:
print("It is a string!")
case builtins.int:
print("It is an integer!")
case builtins.bool:
print("It is a boolean!")
case _:
print(f"It is a {type(v)}!")
Note that a value pattern must be a dotted name; it's not an arbitrary expression that can evaluate to a specific value.
(Whether you really want to match against the actual type of a value, or really want to determine if a value is an instance of a given type, is another matter. In the latter case, an if-elif statement is needed.
if isinstance(v, bool):
print("It is a boolean!")
elif isinstance(v, int):
print("It is an int!")
elif isinstance(v, str):
print("It is a string!")
else:
print(f"It is a {type(v)}!")
There is no pattern that lets you use the result of calling isinstance as the case to match against.
)