其实这只是一个语义问题。
直到最近,如果我必须对一个结构进行任何类型检查,我会使用type(obj) is list
等。但自从加入SO以来,我注意到每个人(我是说每个人)都使用isinstance(obj,list)
。它们似乎是同义词,并且timeit
显示它们之间的速度几乎完全相同。
def a(): return type(list()) is list
def b(): return isinstance(list(),list)
from timeit import timeit
timeit(a)
# 0.5239454597495582
timeit(b)
# 0.5021292075273176
实际上,即使是dis
也认为它们是同义词,除了type is
的COMPARE_OP
之外。
from dis import dis
dis(a)
# 2 0 LOAD_GLOBAL 0 (type)
# 3 LOAD_GLOBAL 1 (list)
# 6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
# 9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
# 12 LOAD_GLOBAL 1 (list)
# 15 COMPARE_OP 8 (is)
# 18 RETURN_VALUE
dis(b)
# 2 0 LOAD_GLOBAL 0 (isinstance)
# 3 LOAD_GLOBAL 1 (list)
# 6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
# 9 LOAD_GLOBAL 1 (list)
# 12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
# 15 RETURN_VALUE
我更喜欢使用if type(foo) is list:
而不是if isinstance(foo,list):
,前者基本上只是伪代码,而后者会调用一些函数(每次都要查找以确定是否为isinstance
或instanceof
),并带有一些参数。它看起来不像类型转换,也没有明确的方式知道isinstance(a,b)
是检查b
是否是a
的实例还是反之。
我从这个问题中了解到我们使用isinstance
,因为它在继承方面更好。当type(ClassDerivedFromList) is list
失败时,isinstance(ClassDerivedFromList,list)
将成功。但如果我正在检查应始终是基础对象的内容,那么使用 type
会失去什么呢?
str
或list
,因此执行if type(foo) is str: _handle_str(foo) else: _handle_list(foo)
是否真的是一种不好的做法? - Adam Smithunicode
和str
之间的陷阱,但我很欣赏它们。 - Adam Smithif type(foo) is list: _handle_list(foo) else: _handle_str(foo)
。@DSM 是完全正确的,为了正确处理字符串,你需要检查isinstance(foo, basestring)
。如果我是你,我会实际检查if type(foo) is list: _handle_list(foo) elif isinstance(foo, basestring): _handle_str(foo) else raise Exception("Type Not Handled")
。 - zmo