杰瑞科技汇

Python isinstance如何判断变量类型?

Of course! Let's dive deep into Python's isinstance() function. It's a fundamental and highly useful built-in function.

Python isinstance如何判断变量类型?-图1
(图片来源网络,侵删)

What is isinstance()?

In simple terms, isinstance() is a function that checks if an object is an instance of a given class or of a subclass thereof. It answers the question: "Does this object belong to this specific type or a type that inherits from it?"

The function returns True if the object is an instance of the specified class (or any of its parent classes) and False otherwise.


The Syntax

The syntax is straightforward:

isinstance(object, classinfo)

Parameters:

Python isinstance如何判断变量类型?-图2
(图片来源网络,侵删)
  • object: The object you want to check. This can be any Python object.
  • classinfo: This is the class (or a tuple of classes) you want to check against.

Return Value:

  • True if object is an instance of classinfo or a subclass of classinfo.
  • False otherwise.

Basic Examples

Let's start with the most common use case: checking an object against a built-in type like int, str, or list.

# --- Checking against a single class ---
# An integer instance
num = 10
print(f"Is 10 an instance of int? {isinstance(num, int)}")
# Output: Is 10 an instance of int? True
# A string instance
text = "hello"
print(f"Is 'hello' an instance of str? {isinstance(text, str)}")
# Output: Is 'hello' an instance of str? True
# A list instance
my_list = [1, 2, 3]
print(f"Is [1, 2, 3] an instance of list? {isinstance(my_list, list)}")
# Output: Is [1, 2, 3] an instance of list? True
# A boolean is a subclass of int in Python
print(f"Is True an instance of int? {isinstance(True, int)}")
# Output: Is True an instance of int? True
# A check that fails
print(f"Is 10 an instance of str? {isinstance(num, str)}")
# Output: Is 10 an instance of str? False

Checking Against Inheritance (The Power of isinstance())

This is where isinstance() truly shines compared to type(). It correctly identifies an object as an instance of its parent class as well.

Let's define a simple class hierarchy:

Python isinstance如何判断变量类型?-图3
(图片来源网络,侵删)
class Animal:
    pass
class Dog(Animal):
    pass
class Cat(Animal):
    pass
# Create an instance of the Dog class
my_dog = Dog()
# Check if my_dog is an instance of Dog
print(f"Is my_dog an instance of Dog? {isinstance(my_dog, Dog)}")
# Output: Is my_dog an instance of Dog? True
# Check if my_dog is an instance of Animal (its parent class)
print(f"Is my_dog an instance of Animal? {isinstance(my_dog, Animal)}")
# Output: Is my_dog an instance of Animal? True
# Check if my_dog is an instance of Cat (a different subclass)
print(f"Is my_dog an instance of Cat? {isinstance(my_dog, Cat)}")
# Output: Is my_dog an instance of Cat? False
# Check if an Animal instance is an instance of Dog
generic_animal = Animal()
print(f"Is generic_animal an instance of Dog? {isinstance(generic_animal, Dog)}")
# Output: Is generic_animal an instance of Dog? False

As you can see, isinstance(my_dog, Animal) returns True because Dog inherits from Animal. This is essential for polymorphism and writing flexible code.


Checking Against Multiple Types (Using a Tuple)

The classinfo parameter can also be a tuple of classes. The function will return True if the object is an instance of any of the classes in the tuple. This is incredibly useful for handling objects that could be of several different types.

def process_data(data):
    if isinstance(data, (int, float)):
        print(f"Processing numeric value: {data * 2}")
    elif isinstance(data, str):
        print(f"Processing string: {data.upper()}")
    else:
        print("Unknown data type")
process_data(100)        # int
process_data(3.14)       # float
process_data("hello")    # str
process_data([1, 2, 3])  # list (will trigger the else clause)
# Output:
# Processing numeric value: 200
# Processing numeric value: 6.28
# Processing string: HELLO
# Unknown data type

isinstance() vs. type()

A common point of confusion is the difference between isinstance() and the type() function.

Feature isinstance(obj, class) type(obj) is class
Primary Use Checking for an object's type in an inheritance hierarchy. Checking for an exact type match. Checking for an exact type match.
Inheritance Respects inheritance. Returns True for parent classes. Does not respect inheritance. Returns False for parent classes.
Flexibility More flexible. Can check against multiple types with a tuple. Less flexible. Can only check against one type at a time.
Best For General type checking, especially in polymorphic code. When you need to be certain an object is exactly that type and not a subclass.

Example to Illustrate the Difference:

class Parent:
    pass
class Child(Parent):
    pass
obj = Child()
# isinstance() returns True because Child is a subclass of Parent
print(f"isinstance(obj, Parent): {isinstance(obj, Parent)}")
# Output: isinstance(obj, Parent): True
# type() returns False because the exact type of obj is Child, not Parent
print(f"type(obj) is Parent: {type(obj) is Parent}")
# Output: type(obj) is Parent: False
# Both return True for the exact class
print(f"isinstance(obj, Child): {isinstance(obj, Child)}")
# Output: isinstance(obj, Child): True
print(f"type(obj) is Child: {type(obj) is Child}")
# Output: type(obj) is Child: True

Rule of Thumb: For 99% of cases, especially when dealing with user-defined classes and polymorphism, you should use isinstance(). It's more robust and aligns with object-oriented principles.


Checking Against Abstract Base Classes (ABCs)

isinstance() also works perfectly with Abstract Base Classes (ABCs) from the abc module, which define a common interface for a group of classes.

from collections.abc import Sequence
# A string is a sequence
my_string = "hello"
print(f"Is 'hello' a Sequence? {isinstance(my_string, Sequence)}")
# Output: Is 'hello' a Sequence? True
# A list is a sequence
my_list = [1, 2, 3]
print(f"Is [1, 2, 3] a Sequence? {isinstance(my_list, Sequence)}")
# Output: Is [1, 2, 3] a Sequence? True
# A set is NOT a sequence (it's not ordered)
my_set = {1, 2, 3}
print(f"Is {{1, 2, 3}} a Sequence? {isinstance(my_set, Sequence)}")
# Output: Is {1, 2, 3} a Sequence? False

Common Pitfalls and "Gotchas"

  1. Don't Use isinstance() with bool and int Carelessly: As mentioned, bool is a subclass of int. True has a value of 1 and False has a value of 0.

    # This will return True, which might be unexpected
    if isinstance(True, int):
        print("True is considered an integer.")
    # Output: True is considered an integer.

    If you want to specifically check for an integer but not a boolean, you need to be more explicit:

    def is_real_integer(obj):
        return type(obj) is int
    print(f"is_real_integer(10): {is_real_integer(10)}")
    print(f"is_real_integer(True): {is_real_integer(True)}")
    # Output:
    # is_real_integer(10): True
    # is_real_integer(True): False
  2. classinfo Must Be a Class or a Tuple of Classes: If you pass anything else, you'll get a TypeError.

    # This will raise a TypeError
    isinstance(10, "not a class") # Raises TypeError: isinstance() arg 2 must be a type or tuple of types

Summary: When to Use isinstance()

Use isinstance() when you want to:

  • Check if an object belongs to a specific type.
  • Check if an object belongs to a type or any of its parent types. (This is its main advantage).
  • Handle objects that could be one of several different types. (By passing a tuple).
  • Work with Abstract Base Classes to check for interface compliance.
  • Write clean, polymorphic code that can work with any object that adheres to a certain "contract" (i.e., is an instance of a certain class hierarchy).
分享:
扫描分享到社交APP
上一篇
下一篇