获取对象信息

Python 对象类型检查与方法获取指南

1. 类型检查

1.1 使用 type() 函数

type() 函数是最直接的获取对象类型的方法:

# 基本类型检查
print(type(123))        # <class 'int'>
print(type('str'))      # <class 'str'>
print(type(3.14))       # <class 'float'>
print(type(True))       # <class 'bool'>
print(type(None))       # <class 'NoneType'>

# 函数和类检查
def my_func(): pass
class MyClass: pass

print(type(my_func))    # <class 'function'>
print(type(MyClass))    # <class 'type'>
print(type(MyClass()))  # <class '__main__.MyClass'>

可以直接比较类型:

print(type(123) == int)          # True
print(type('abc') == str)        # True
print(type([1,2,3]) == list)     # True

1.2 检查函数类型

对于函数类型检查,可以使用 types 模块:

import types

def my_func(): pass
lambda_func = lambda x: x
gen = (x for x in range(3))

print(type(my_func) == types.FunctionType)       # True
print(type(lambda_func) == types.LambdaType)     # True
print(type(gen) == types.GeneratorType)          # True
print(type(abs) == types.BuiltinFunctionType)    # True

1.3 使用 isinstance() 函数

对于继承关系的检查,isinstance() 更合适:

class Animal: pass
class Dog(Animal): pass
class Husky(Dog): pass

a = Animal()
d = Dog()
h = Husky()

print(isinstance(h, Husky))  # True
print(isinstance(h, Dog))    # True (父类)
print(isinstance(h, Animal)) # True (祖父类)
print(isinstance(d, Husky))  # False

isinstance() 也可以检查基本类型:

print(isinstance('a', str))       # True
print(isinstance(123, int))       # True
print(isinstance([1,2], list))    # True
print(isinstance((1,2), tuple))   # True

可以一次检查多种类型:

print(isinstance([1,2], (list, tuple)))  # True
print(isinstance((1,2), (list, tuple)))  # True

最佳实践:优先使用 isinstance() 而不是 type(),因为它能正确处理继承关系。

2. 获取对象属性和方法

2.1 使用 dir() 函数

dir() 返回对象的所有属性和方法列表:

print(dir('ABC'))  # 列出字符串的所有方法和属性

特殊方法通常以双下划线开头和结尾,如 __len__

s = 'hello'
print(len(s) == s.__len__())  # True

自定义类实现 __len__

class MyCollection:
    def __len__(self):
        return 100

col = MyCollection()
print(len(col))  # 100

2.2 动态属性操作

使用 hasattr(), getattr(), setattr() 动态操作属性:

class MyObject:
    def __init__(self):
        self.x = 9
    def power(self):
        return self.x ** 2

obj = MyObject()

# 检查属性
print(hasattr(obj, 'x'))      # True
print(hasattr(obj, 'y'))      # False

# 获取属性
print(getattr(obj, 'x'))      # 9
print(getattr(obj, 'y', 404)) # 404 (默认值)

# 设置属性
setattr(obj, 'y', 10)
print(hasattr(obj, 'y'))      # True
print(obj.y)                  # 10

# 方法操作
print(hasattr(obj, 'power'))  # True
power_method = getattr(obj, 'power')
print(power_method())         # 81

3. 实际应用示例

3.1 鸭子类型检查

def read_data(source):
    if hasattr(source, 'read'):
        return source.read()
    else:
        return str(source)

class StringIO:
    def __init__(self, data):
        self.data = data
    def read(self):
        return self.data

print(read_data("hello"))          # hello
print(read_data(StringIO("hi")))   # hi

3.2 动态调用方法

class Processor:
    def process_text(self, text):
        return text.upper()
    
    def process_number(self, num):
        return num * 2

processor = Processor()
data = ['hello', 10]

for item in data:
    if isinstance(item, str):
        method = getattr(processor, 'process_text')
    elif isinstance(item, (int, float)):
        method = getattr(processor, 'process_number')
    print(method(item))

# 输出:
# HELLO
# 20

4. 总结

  1. 类型检查

    • 使用 type() 进行精确类型匹配
    • 使用 isinstance() 处理继承关系
    • 使用 types 模块检查函数类型
  2. 属性和方法检查

    • dir() 获取所有属性和方法
    • hasattr() 检查属性/方法是否存在
    • getattr() 动态获取属性/方法
    • setattr() 动态设置属性
  3. 最佳实践

    • 优先使用 isinstance() 进行类型检查
    • 仅在需要动态处理对象时才使用反射方法
    • 遵循鸭子类型原则,关注对象能力而非具体类型

这些技术是 Python 元编程和动态特性的重要组成部分,合理使用可以使代码更加灵活和强大。