Isinstance (foo, bar) vs type (foo) является баром
Вопрос о семантике, действительно.
До недавнего времени, если бы мне пришлось выполнять какую-либо проверку типов в структуре, я бы использовал 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
?
Ответы
Ответ 1
если я проверяю, что ВСЕГДА БЫТЬ БАЗОВЫМ ОБЪЕКТОМ, что я действительно теряю от типа?
Хорошо, хорошо, что вы даете полный документированный ответ в своем вопросе, поэтому ваш ответ заключается в том, что вы ничего не теряете! Единственное время, когда isinstance()
необходимо, - это проверять наследование данного класса по сравнению с другим, как вы сказали и ссылаетесь. type()
используется только для проверки того, является ли экземпляр точно заданным базовым типом.
Ответ 2
Помимо проблемы наследования, вы также теряете возможность тестировать несколько типов при использовании isinstance
. Например:
def chk(typ):
if not isinstance(typ, (str, int)):
raise ValueError('typ must be string or int')
...
Ответ 3
Ответ на ваш вопрос:
Нет, учитывая, что вы проверяете определенный базовый класс, поскольку вы теряете способность тестировать наследуемые классы.
И IMO isinstance
лучше читать и в Python: читаемость подсчитывается.
PS: Я получаю существенную разницу в таймингах (на Python 3.3)
type: 0.5241982917936874
isinstance: 0.46066255811928847
Ответ 4
Документы Python для встроенной функции типа обеспечивают четкое руководство по разнице между типом (с одним аргументом) и isinstance.
С одним аргументом верните тип объекта. Возвращаемое значение представляет собой объект типа и, как правило, тот же объект, что и возвращаемый объектом. class.
Встроенная функция isinstance() рекомендуется для тестирования типа объекта, поскольку он учитывает подклассы.
Чтобы проиллюстрировать это, посмотрите иерархию наследования ниже в модульном диалоге:
![введите описание изображения здесь]()
Затем взгляните на вывод консоли python ниже на основе модуля diamond:
![введите описание изображения здесь]()
В соответствии с документацией он более универсален и может охватывать более широкий спектр сценариев. Что касается оригинального вопроса OP, характеристики производительности не были указаны в качестве веской причины одобрения одного над другим. Также не было удобочитаемости.
Для более углубленного обсуждения, которое включает объяснение (в словах ответчика) "почему проверка равенства типов является еще более худшей практикой в последних версиях Python, чем она уже была", см. это проголосовали ответ