The isinstance() function is a fundamental tool in Python for checking an object's type. The TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union arises when the second argument provided to isinstance() is not what Python expects for type checking. Usually, this means you've passed a list or another non-type object instead of a single type object (like str, int, list) or a tuple containing type objects.
This guide explains the correct usage of isinstance()'s second argument and provides solutions for the common mistakes that lead to this error.
Understanding the Error: isinstance() Syntax
The isinstance() function checks if an object is an instance of a particular class or a subclass thereof. Its syntax is:
isinstance(object, classinfo)
object: The object whose type you want to check.classinfo: This is where the error occurs. This argument must be either:- A single type object (e.g.,
int,str,list,dict,float,bool, a custom class name). - A tuple containing two or more type objects (e.g.,
(str, int),(list, tuple, set)). The function returnsTrueif theobjectis an instance of any of the types in the tuple.
- A single type object (e.g.,
The TypeError occurs because the value passed as the classinfo argument doesn't fit these requirements – most commonly, it's a list instance or another non-type object.
Cause 1: Passing a List Instead of a Tuple for Multiple Types
When checking if an object belongs to one of several possible types, you must provide those types within a tuple, not a list.
Error Scenario
value = 123
allowed_types_list = [str, int, float] # This is a LIST of types
print(f"Type of allowed_types_list: {type(allowed_types_list)}") # Output: <class 'list'>
try:
if isinstance(value, allowed_types_list):
print("Value is of an allowed type.")
except TypeError as e:
print(e)Output:
Type of allowed_types_list: <class 'list'>
isinstance() arg 2 must be a type or tuple of typesSolution: Use a Tuple of Types
Provide the multiple types within a tuple () directly, or convert your list of types to a tuple using tuple().
value = 123
allowed_types_list = [str, int, float]
allowed_types_tuple = tuple(allowed_types_list)
print(f"Type of allowed_types_tuple: {type(allowed_types_tuple)}") # Output: <class 'tuple'>
if isinstance(value, allowed_types_tuple):
print(f"Value {value} is an instance of one of {allowed_types_tuple} (using tuple conversion).") # This is executed
else:
print(f"Value {value} is not an instance (using tuple conversion).")
if isinstance(value, (str, int, float)): # Pass tuple literal directly
print(f"Value {value} is an instance of one of (str, int, float) (using tuple literal).") # This is executed
else:
print(f"Value {value} is not an instance (using tuple literal).")
another_value = "hello"
if isinstance(another_value, (str, int, float)):
print(f"Value '{another_value}' is an instance of one of (str, int, float).") # This is executedOutput:
Type of allowed_types_tuple: <class 'tuple'>
Value 123 is an instance of one of (<class 'str'>, <class 'int'>, <class 'float'>) (using tuple conversion).
Value 123 is an instance of one of (str, int, float) (using tuple literal).
Value 'hello' is an instance of one of (str, int, float).Using a tuple literal (type1, type2, ...) directly is usually the clearest approach.
Cause 2: Shadowing Built-in Type Names
This error can also occur if you unintentionally assign a value (especially a list or other non-type object) to a variable that has the same name as a built-in type (like list, str, dict, int). This is called "shadowing."
Error Scenario
list = ["apple", "banana"] # 'list' now refers to this specific list instance
my_data = [1, 2, 3]
print(f"Value of shadowed 'list': {list}")
print(f"Type of shadowed 'list': {type(list)}")
try:
if isinstance(my_data, list):
print("my_data is a list.")
except TypeError as e:
print(e)Output:
Value of shadowed 'list': ['apple', 'banana']
Type of shadowed 'list': <class 'list'>
isinstance() arg 2 must be a type or tuple of typesBecause the name list was reassigned, it no longer refers to the built-in list type object that isinstance() expects. It refers to the actual list instance ["apple", "banana"].
Solution 1: Rename the Shadowing Variable (Recommended)
The best and cleanest solution is to avoid shadowing built-in type names. Rename your variable to something descriptive that doesn't conflict.
my_string_list = ["apple", "banana"] # Use a different name
my_data = [1, 2, 3]
if isinstance(my_data, list):
print("my_data is a list (after renaming variable).") # This is executed
else:
print("my_data is not a list (after renaming variable).")Solution 2: Use type() to Get the Type (Workaround)
If renaming the variable is absolutely not feasible (which is rare and usually indicates a need for code refactoring), you can get the type of the shadowing variable using type() and pass that to isinstance().
list = ["apple", "banana"] # 'list' is the instance
my_data = [1, 2, 3]
list_type_obj = type(list) # This correctly gets <class 'list'>
print(f"Type obtained via type(list): {list_type_obj}")
if isinstance(my_data, list_type_obj):
print("my_data is a list (using type() workaround).") # This is executed
if isinstance(my_data, type([])): # type([]) also returns <class 'list'>
print("my_data is a list (using type([]) workaround).") # This is executedOutput:
Type obtained via type(list): <class 'list'>
my_data is a list (using type() workaround).
my_data is a list (using type([]) workaround).Debugging the Error
When isinstance() raises this TypeError:
- Focus on the second argument passed to
isinstance(). - Print its value and type just before the
isinstance()call:print(f"DEBUG: Arg 2 value: {repr(second_argument)}") print(f"DEBUG: Arg 2 type: {type(second_argument)}") - If the type is
list: You need to convert it to a tuple (tuple(second_argument)) or rewrite it as a tuple literal(type1, type2). - If the type is NOT
typeortuple: You've likely shadowed a built-in type name with a variable. Find the variable assignment and rename the variable.
Conclusion
The TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union occurs when the second argument provided to isinstance() is invalid for type checking.
The main solutions are:
- When checking against multiple types, provide them within a tuple
(type1, type2, ...), not a list[type1, type2, ...]. - Avoid shadowing built-in type names (like
list,str,dict,int) with your variable names. Rename conflicting variables (e.g., usemy_listinstead oflist).
By ensuring the second argument to isinstance() is always a type object or a tuple of type objects, you can effectively use it for robust type checking in Python.