Question: I want to use match to determine an action to perform based on a class type. I cannot seem to figure out how to do it. I know their are other ways of achieving this, I would just like to know can it be done this way. I am not looking for workarounds of which there are many.  class aaa(): pass class bbb(): pass def f1(typ): if typ is aaa: print("aaa") elif typ is bbb: print("bbb") else: print("???") def f2(typ): match typ: case aaa(): print("aaa") case bbb(): print("bbb") case _: print("???") f1(aaa) f1(bbb) f2(aaa) f2(bbb)  The output is as follows: aaa bbb ??? ??? 

Answer: Try using typ() instead of typ in the match line:  class aaa(): pass class bbb(): pass def f1(typ): if typ is aaa: print("aaa") elif typ is bbb: print("bbb") else: print("???") def f2(typ): match typ(): case aaa(): print("aaa") case bbb(): print("bbb") case _: print("???") f1(aaa) f1(bbb) f2(aaa) f2(bbb)  Output: aaa bbb aaa bbb  UPDATE: Based on OP's comment asking for solution that works for classes more generally than the example classes in the question, here is an answer addressing this: class aaa(): pass class bbb(): pass def f1(typ): if typ is aaa: print("aaa") elif typ is bbb: print("bbb") else: print("???") def f2(typ): match typ.__qualname__: case aaa.__qualname__: print("aaa") case bbb.__qualname__: print("bbb") case _: print("???") f1(aaa) f1(bbb) f2(aaa) f2(bbb)  Output: aaa bbb aaa bbb  UPDATE #2: Based on this post and some perusal of PEP 364 here, I have created an example showing how a few data types (a Python builtin, a class from the collections module, and a user defined class) can be used by match to determine an action to perform based on a class type (or more generally, a data type): class bbb: pass class namespacing_class: class aaa: pass def f1(typ): if typ is aaa: print("aaa") elif typ is bbb: print("bbb") else: print("???") def f2(typ): match typ.__qualname__: case aaa.__qualname__: print("aaa") case bbb.__qualname__: print("bbb") case _: print("???") def f3(typ): import collections match typ: case namespacing_class.aaa: print("aaa") case __builtins__.str: print("str") case collections.Counter: print("Counter") case _: print("???") ''' f1(aaa) f1(bbb) f2(aaa) f2(bbb) ''' f3(namespacing_class.aaa) f3(str) import collections f3(collections.Counter)  Outputs: aaa str Counter  As stated in this answer in another post:  A variable name in a case clause is treated as a name capture pattern. It always matches and tries to make an assignment to the variable name. ... We need to replace the name capture pattern with a non-capturing pattern such as a value pattern that uses the . operator for attribute lookup. The dot is the key to matching this a non-capturing pattern.  In other words, if we try to say case aaa: for example, aaa will be interpreted as a name to which we assign the subject (typ in your code) and will always match and block any attempts to match subsequent case lines. To get around this, for class type names (or names generally) that can be specified using a dot (perhaps because they belong to a namespace or another class), we can use the dotted name as a pattern that will not be interpreted as a name capture. For built-in type str, we can use case __builtins__.str:. For the Counter class in Python's collections module, we can use case collections.Counter:. If we define class aaa within another class named namespacing_class, we can use case namespacing_class.aaa:. However, if we define class bbb at the top level within our Python code, it's not clear to me that there is any way to use a dotted name to refer to it and thereby avoid name capture. It's possible there's a way to specify a user defined class type in a case line and I simply haven't figured it out yet. Otherwise, it seems rather arbitrary (and unfortunate) to be able to do this for dottable types and not for non-dottable ones.