Вопрос о семантике, действительно.
До недавнего времени, если бы мне пришлось выполнять какую-либо проверку типов в структуре, я бы использовал type(obj) is list
et. и др. Однако, так как я присоединился к SO, я заметил, что каждый (и я имею в виду ВСЕ) использует isinstance(obj,list)
вместо этого. Кажется, что они синонимы, а timeit
показывает почти IDENTICAL скорость между ними.
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 is
?