Каковы различия между этими двумя фрагментами кода?
Использование type()
:
import types
if type(a) is types.DictType:
do_something()
if type(b) in types.StringTypes:
do_something_else()
Использование isinstance()
:
if isinstance(a, dict):
do_something()
if isinstance(b, str) or isinstance(b, unicode):
do_something_else()
python
oop
inheritance
types
аббат
источник
источник
str
иunicode
(где вы можете просто проверитьbasestring
), вы можете использовать кортеж для проверки нескольких типов. Чтобы проверить, еслиsomething
естьint
илиstr
используйтеisinstance(something, (int, str))
.Ответы:
Подводя итог содержанию других (уже хороших!) Ответов,
isinstance
обслуживает наследование (экземпляр производного класса также является экземпляром базового класса), а проверка на равенство -type
нет (требует идентификации типов и отклоняет экземпляры). подтипов, подклассы АКА).Как правило, в Python вы хотите, чтобы ваш код поддерживал наследование (конечно, поскольку наследование очень удобно, было бы плохо не использовать код, использующий ваш!), Так что
isinstance
это не так плохо, как проверка идентичностиtype
s, потому что он полностью поддерживает наследование.Это не значит, что
isinstance
это хорошо , заметьте, это просто так плохо , чем проверка равенства типов. Нормальное, предпочтительное для Pythonic решение - это почти всегда «типизированная утка»: попробуйте использовать аргумент, как если бы он был определенного желаемого типа, сделайте это в оператореtry
/,except
перехватив все исключения, которые могут возникнуть, если аргумент не является фактическим. type (или любой другой тип, прекрасно имитирующий утку ;-), и вexcept
предложении попробуйте что-нибудь другое (используя аргумент «как будто», он был другого типа).basestring
это , однако, довольно особый случай - встроенный тип, который существует только для того, чтобы вы могли его использоватьisinstance
(какstr
иunicode
подклассbasestring
). Строки - это последовательности (вы можете зациклить их, проиндексировать их, нарезать их, ...), но вы, как правило, хотите рассматривать их как «скалярные» типы - это несколько неудобно (но достаточно часто используется) для обработки всех видов строки (и, возможно, другие скалярные типы, т. е. те, которые вы не можете зациклить) одним способом, все контейнеры (списки, наборы, подсказки, ...) другим способом, иbasestring
плюсisinstance
помогает вам сделать это - общая структура этого идиома это что-то вроде:Можно сказать, что
basestring
это абстрактный базовый класс («ABC») - он не предлагает никаких конкретных функций для подклассов, а скорее существует как «маркер», в основном для использования сisinstance
. Эта концепция явно расширяется в Python, поскольку PEP 3119 , который вводит ее обобщение, был принят и реализован начиная с Python 2.6 и 3.0.PEP ясно дает понять, что, хотя ABC часто могут заменить типизацию утки, как правило, нет большого давления, чтобы сделать это (см. Здесь ). Однако ABC, реализованные в последних версиях Python, предлагают дополнительные плюсы:
isinstance
(иissubclass
) теперь может означать больше, чем просто «[экземпляр] производного класса» (в частности, любой класс может быть «зарегистрирован» в ABC, так что он будет показать как подкласс, а его экземпляры как экземпляры ABC); и ABC могут также предложить дополнительное удобство для реальных подклассов очень естественным способом с помощью шаблонных приложений шаблонного метода (см. здесь и здесь [[часть II]] для получения дополнительной информации о TM DP, в целом и особенно в Python, независимо от ABC) ,Основную механику поддержки ABC, предложенную в Python 2.6, смотрите здесь ; для их версии 3.1, очень похожей, смотрите здесь . В обеих версиях стандартные коллекции модулей библиотеки (это версия 3.1 - для очень похожей версии 2.6, см. Здесь ) предлагают несколько полезных ABC.
Для целей этого ответа главное, что следует сохранить в ABC (помимо, возможно, более естественного размещения функциональности TM DP, по сравнению с классической Python-альтернативой смешанных классов, таких как UserDict.DictMixin ), заключается в том, что они делают
isinstance
(иissubclass
) намного больше привлекательный и распространенный (в Python 2.6 и в дальнейшем), чем раньше (в 2.5 и ранее), и поэтому, напротив, проверка равенства типов является еще худшей практикой в последних версиях Python, чем это было раньше.источник
Вот пример, где
isinstance
достигается то, чтоtype
не может:в этом случае объект грузовика - это Автомобиль, но вы получите следующее:
Другими словами,
isinstance
верно и для подклассов.Также см .: Как сравнить тип объекта в Python?
источник
type
устарело, используйтеisinstance
вместо» на первый взгляд. например, то, что я хотел, было именноtype()
проверкой, но я был введен в заблуждение в течение короткого времени (и должен был немного отладить) по этой причине.type()
и не нужноisinstance()
. Один не лучше; они для разных вещей.Проверка типа с
допускает экземпляры подклассов и несколько возможных баз:
тогда как проверка типа с
поддерживает только указанный тип.
В качестве sidenote,
is
вероятно, более подходящим, чемпотому что классы синглтоны.
Избегайте проверки типов - используйте Polymorphism (duck-typing)
В Python, как правило, вы хотите разрешить любой тип для ваших аргументов, обрабатывать его как положено, и если объект не ведет себя должным образом, он вызовет соответствующую ошибку. Это известно как полиморфизм, также известный как типирование утки.
Если приведенный выше код работает, мы можем предположить, что наш аргумент - утка. Таким образом мы можем передать в другие вещи актуальные подтипы утки:
или это работает как утка
и наш код все еще работает.
Однако в некоторых случаях желательно явно проверять тип. Возможно, вы имеете дело с разными типами объектов. Например, объект Dataframe Pandas может быть создан из диктовок или записей. В таком случае ваш код должен знать, какой тип аргумента он получает, чтобы он мог правильно с ним справиться.
Итак, чтобы ответить на вопрос:
Различия между
isinstance()
иtype()
в Python?Позвольте мне продемонстрировать разницу:
type
Скажем, вам нужно обеспечить определенное поведение, если ваша функция получает аргумент определенного типа (общий вариант использования для конструкторов). Если вы проверите для типа, как это:
Если мы попытаемся передать dict, который является подклассом
dict
(как мы должны быть в состоянии, если мы ожидаем, что наш код будет следовать принципу подстановки Лискова , эти подтипы могут быть заменены типами), наш код нарушится !:выдает ошибку!
isinstance
Но если мы воспользуемся
isinstance
, мы можем поддержать замену Лискова!возвращается
OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
Абстрактные базовые классы
На самом деле, мы можем сделать еще лучше.
collections
предоставляет абстрактные базовые классы, которые обеспечивают минимальные протоколы для различных типов. В нашем случае, если мы ожидаем толькоMapping
протокола, мы можем сделать следующее, и наш код станет еще более гибким:Ответ на комментарий:
Да, вы можете проверить на равенство типов, но вместо вышеперечисленного используйте несколько баз для потока управления, если только вы специально не разрешаете только эти типы:
Разница, опять же, в том, что он
isinstance
поддерживает подклассы, которые можно заменить родителем, не нарушая при этом программу, свойство, известное как подстановка Лискова.Еще лучше, однако, инвертировать ваши зависимости и вообще не проверять конкретные типы.
Вывод
Так как мы хотим поддерживать замену подклассов, в большинстве случаев мы хотим избегать проверки типов с помощью
type
и предпочитаем проверку типов с помощьюisinstance
- если вам действительно не нужно знать точный класс экземпляра.источник
isinstance(instance, y)
и используетеfrom v.w.x import y
, и вы импортируете эту проверку, но при создании экземпляраinstance
вы используетеfrom x import y
вместо того, как y был импортирован в your_module.py, проверка isinstance завершится неудачей, даже если это тот же класс.Последний является предпочтительным, потому что он будет правильно обрабатывать подклассы. Фактически, ваш пример может быть написан еще проще, поскольку
isinstance()
второй параметр может быть кортежем:или, используя
basestring
абстрактный класс:источник
В соответствии с документацией Python вот заявление:
Так что
isinstance()
стоит отдать предпочтениеtype()
.источник
Разница в практическом использовании заключается в том, как они обрабатывают
booleans
:True
иFalse
просто ключевые слова, которые означают1
и0
в Python. Таким образом,а также
оба возвращаются
True
. Оба логических значения являются экземпляром целого числа.type()
Впрочем, умнее:возвращается
False
.источник
Для реальных отличий мы можем найти это
code
, но я не могу найти реализацию поведения по умолчаниюisinstance()
.Однако мы можем получить аналогичный abc .__ instancecheck__ в соответствии с __instancecheck__ .
Сверху
abc.__instancecheck__
, после использования теста ниже:Я получаю этот вывод, для
type
:Для
isinstance
:Кстати: лучше не смешивать использование
relative and absolutely import
, используйтеabsolutely import
из project_dir (добавленоsys.path
)источник