Подтвердить что ты не робот

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?

4b9b3361

Ответ 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, чем она уже была", см. это проголосовали ответ