isinstance(object, classinfo)
用于检查类型
判断 obj
对象是否为 classinfo
对应类型的实例或者其子类的实例,是则返回 True
,否则返回 False
object
为待检查的对象classinfo
的类型为Type
或 包含了Type
的tuple
- 如果
classinfo
传入的参数类型不匹配,那么会抛出TypeError
异常
Python3.10
中classinfo
类型可以为Union
isinstance(obj, (A, B, C))
# 等同于
isinstance(obj, A) or isinstance(obj, B) or isinstance(obj, C)
遇到的问题
用 Scrapy 写项目时,定义了异常类 ParseError
,以及自定义的SpiderMiddleware 用于处理该类异常,使用 isinstance
函数来判断异常是否为 ParseError
,发现对于是相同类型的对象, isinstance
仍然返回 False
;
输出异常类型以及 ParseError
的信息,发现 <class 'data_scrapy.announcement_scrapy.components.parseerror.ParseError'> <class 'announcement_scrapy.components.parseerror.ParseError'>
二者之间仅相差一个前缀不同,导致了该函数返回 False
;
后面使用 id()
输出对应类型的值,也是不相等;
def process_spider_exception(self, response, exception, spider: Spider):
print(type(exception), ParseError)
# <class 'data_scrapy.announcement_scrapy.components.parseerror.ParseError'> <class 'announcement_scrapy.components.parseerror.ParseError'>
print(id(exception.__class__), id(ParseError))
if isinstance(exception, ParseError): # 返回 False
error = spider.logger.error
# ...
Python的导入机制会根据导入路径来决定模块的命名空间,即使是同一个模块,如果导入路径不同,Python也会认为它们是两个不同的模块。
统一导入方式防止上述情况发生,在 process_spider_exception
中对 ParseError
加上相同的前缀:data_scrapy.announcement_scrapy.components.parseerror.ParseError
即可
类的重载
如果类发生了重载 reload,也会导致 isinstance
返回False
举个例子:
if __name__ == '__main__':
class A:
pass
a = A()
print(isinstance(a, A), type(A), id(A))
class A:
pass
print(isinstance(a, A), type(A), id(A))
"""
结果:
True <class 'type'> 2136731130064
False <class 'type'> 2136731139664
"""
例子中可以看到,类发生重载后,即使 type()
返回信息相同,但是 id()
返回信息不同,导致 isinstance()
返回 False