Есть ли простой способ определить, является ли переменная списком, словарем или чем-то еще? Я возвращаю объект, который может быть любого типа, и я должен быть в состоянии отличить.
python
dictionary
types
typeof
Джастин этир
источник
источник
try
который не помогает. Например, если вы знали, что пользователь может передать строку или массив, оба могут индексировать, но этот индекс означает нечто совершенно иное. Просто полагаться на попытку в таких случаях не получится неожиданным и странным образом. Одно из решений - создать отдельный метод, другое - добавить небольшую проверку типов. Лично я предпочитаю полиморфное поведение нескольким методам, которые делают почти одно и то же ... но это только я :)Ответы:
Есть две встроенные функции, которые помогут вам определить тип объекта. Вы можете использовать ,
type()
если вам нужен точный тип объекта, иisinstance()
чтобы проверить тип объекта против чего - то. Обычно вы хотите использоватьisistance()
большую часть времени, так как он очень надежен и поддерживает наследование типов.Чтобы получить фактический тип объекта, вы используете встроенную
type()
функцию. Передача объекта в качестве единственного параметра вернет объект типа этого объекта:Это, конечно, также работает для пользовательских типов:
Обратите внимание, что он
type()
будет возвращать только непосредственный тип объекта, но не сможет рассказать вам о наследовании типов.Чтобы покрыть это, вы должны использовать
isinstance
функцию. Это, конечно, также работает для встроенных типов:isinstance()
обычно является предпочтительным способом обеспечения типа объекта, поскольку он также будет принимать производные типы. Поэтому, если вам не нужен объект типа (по какой-либо причине), использованиеisinstance()
предпочтительнее, чемtype()
.Второй параметр
isinstance()
также принимает кортеж типов, поэтому можно проверять сразу несколько типов.isinstance
затем вернет true, если объект имеет любой из этих типов:источник
is
вместо==
как типы одиночекisinstance
это предпочтительная форма, так==
или иначе, или ее неis
нужно использовать.type
лучший ответ. Есть времена, когдаisinstance
это лучший ответ, и бывают случаи, когда утка - лучший ответ. Важно знать все варианты, чтобы вы могли выбрать наиболее подходящий для ситуации.type(foo) is SomeType
было бы лучше, чемisinstance(foo, SomeType)
.isinstance
для своего сценария использования (проверка на диапазон типов), и с а также чистый синтаксис, который имеет большое преимущество в том, что вы можете захватывать подклассы. кто-то, пользующийся,OrderedDict
будет ненавидеть ваш код, потому что он просто принимает чистые слова.Вы можете сделать это используя
type()
:источник
Это может быть более Pythonic, чтобы использовать
try
...except
блок. Таким образом, если у вас есть класс , который крякает как список, или крякает как Dict, он будет вести себя должным образом , независимо от того, что его типа на самом деле является.Чтобы уточнить, предпочтительный метод «определения различий» между типами переменных - это то, что называется утиной типизацией : пока методы (и возвращаемые типы), на которые отвечает переменная, - это то, что ожидает ваша подпрограмма, обрабатывайте ее так, как вы ожидаете быть. Например, если у вас есть класс, который перегружает операторы скобок с помощью
getattr
иsetattr
, но использует какую-то забавную внутреннюю схему, было бы целесообразно, чтобы он вел себя как словарь, если это то, что он пытается эмулировать.Другая проблема, связанная с
type(A) is type(B)
проверкой, заключается в том, что еслиA
это подклассB
, он оценивает,false
когда программным путем вы бы надеялись, что так и будетtrue
. Если объект является подклассом списка, он должен работать как список: проверка типа, представленного в другом ответе, предотвратит это. (isinstance
будет работать, однако).источник
try
...except
является хорошим решением, когда вы хотите иметь дело с ошибками, но не при выборе поведения на основе типа.На экземплярах объекта у вас также есть:
атрибут. Вот пример, взятый из консоли Python 3.3
Помните, что в Python 3.x и в классах New-Style (возможно, из Python 2.6) класс и тип были объединены, и это может иногда привести к неожиданным результатам. Главным образом по этой причине мой любимый способ тестирования типов / классов - встроенная функция isinstance .
источник
__class__
в основном работает нормально в Python 2.x, единственные объекты в Python, которые не имеют__class__
атрибутов, это классы старого стиля AFAIK. Кстати, я не понимаю вашу озабоченность Python 3 - в такой версии просто у каждого объекта есть__class__
атрибут, который указывает на соответствующий класс.Определить тип объекта Python
Определите тип объекта с помощью
type
Хотя это работает, избегайте атрибутов двойного подчеркивания, таких как
__class__
- они не являются семантически открытыми, и, хотя, возможно, и не в этом случае, встроенные функции обычно ведут себя лучше.проверка типа
Ну, это другой вопрос, не используйте тип - используйте
isinstance
:Это относится к случаю, когда ваш пользователь может делать что-то умное или разумное путем
str
создания подклассов - согласно принципу подстановки Лискова, вы хотите иметь возможность использовать экземпляры подкласса, не нарушая свой код, - иisinstance
поддерживает это.Используйте Абстракции
Более того, вы можете искать конкретный абстрактный базовый класс из
collections
илиnumbers
:Или просто явно не проверяйте тип
Или, может быть, лучше всего, использовать Duck-типирование и не проверять код явно. Duck-typing поддерживает Liskov Substitution более элегантно и менее многословно.
Вывод
type
чтобы фактически получить класс экземпляра.isinstance
для явной проверки на наличие подклассов или зарегистрированных абстракций.источник
try
/except
вместо проверки явно.Вы можете использовать
type()
илиisinstance()
.Имейте в
list
виду, что вы можете использовать clobber или любой другой тип, назначая переменную в текущей области с тем же именем.Выше мы видим, что
dict
переназначается на строку, поэтому тест:... не получается.
Чтобы обойти это и использовать
type()
более осторожно:источник
dict
строка также потерпит неудачу для большого количества другого кода, напримерdict([("key1", "value1"), ("key2", "value2")])
. Ответ на такие вопросы: «Тогда не делай этого» . Не скрывайте встроенные имена типов и не ожидайте, что все будет работать правильно.Хотя вопросы довольно старые, я наткнулся на это, когда сам нашел правильный путь, и я думаю, что он все еще нуждается в разъяснении, по крайней мере для Python 2.x (не проверял на Python 3, но так как проблема возникает с классическими классами которые ушли на такой версии, это, вероятно, не имеет значения).
Здесь я пытаюсь ответить на вопрос заголовка: как я могу определить тип произвольного объекта ? Другие предложения об использовании или неиспользовании isinstance хороши во многих комментариях и ответах, но я не рассматриваю эти проблемы.
Основная проблема этого
type()
подхода заключается в том, что он не работает должным образом с экземплярами старого стиля :Выполнение этого фрагмента даст:
Что, я утверждаю, не то, чего ожидали бы большинство людей.
__class__
Подход наиболее близок к правильности, но он не будет работать в одном решающем случае: когда Переданный объект является старым стиль класс (! Не экземпляр), так как эти объекты не имеет такой атрибут.Это наименьший фрагмент кода, о котором я мог подумать, который последовательно удовлетворяет такой законный вопрос:
источник
будьте осторожны, используя isinstance
но типа
источник
В
collections.abc
дополнение к предыдущим ответам, стоит упомянуть о существовании, которое содержит несколько абстрактных базовых классов (ABC), которые дополняют типизацию утки.Например, вместо явной проверки, является ли что-то списком с:
если вы хотите узнать, позволяет ли ваш объект получать предметы, вы можете использовать
collections.abc.Sequence
:если вы строго заинтересованы в объектах, которые позволяют получать, устанавливать и удалять элементы (например, изменяемые последовательности), вы бы выбрали
collections.abc.MutableSequence
.Многие другие ABCs определяются там,
Mapping
для объектов , которые могут быть использованы в качестве карты,Iterable
,Callable
и так далее. Полный список всего этого можно увидеть в документации поcollections.abc
.источник
Как правило, вы можете извлечь строку из объекта с именем класса,
и использовать его для сравнения,
источник
Во многих практических случаях вместо использования
type
илиisinstance
вы также можете использовать@functools.singledispatch
, который используется для определения универсальных функций ( функция, состоящая из нескольких функций, реализующих одну и ту же операцию для разных типов ).Другими словами, вы хотели бы использовать его, когда у вас есть код, подобный следующему:
Вот небольшой пример того, как это работает:
Кроме того, мы можем использовать абстрактные классы для одновременного покрытия нескольких типов:
источник
type()
является лучшим решением, чемisinstance()
, в частности, дляbooleans
:True
иFalse
просто ключевые слова, которые означают1
и0
в Python. Таким образом,а также
оба возвращаются
True
. Оба логических значения являются экземпляром целого числа.type()
Впрочем, умнее:возвращается
False
.источник