Как сравнить тип объекта в Python?

163

В основном я хочу сделать это:

obj = 'str'
type ( obj ) == string

Я попытался:

type ( obj ) == type ( string )

и это не сработало.

Кроме того, как насчет других типов? Например, я не мог воспроизвести NoneType.

Джоан Венге
источник
Это работаетtype(obj) == str
Джошуа Варгезе

Ответы:

241
isinstance()

В твоем случае isinstance("this is a string", str)вернется True.

Вы также можете прочитать это: http://www.canonical.org/~kragen/isinstance/

Энтони
источник
4
Я бы сказал, что вы (ОП) обязательно должны прочитать ссылочную ссылку, которая дает множество деталей о том, почему проверка типа объекта обычно является плохой идеей, и что вы, вероятно, должны делать вместо этого.
Джефф Шеннон
2
Вы должны использовать basestr, а не str. в противном случае вы не выберете Unicode. (хотя для 3.x я думаю, что str является basestr)
hasen
36

isinstance работает:

if isinstance(obj, MyClass): do_foo(obj)

но имейте в виду: если это похоже на утку, и если это звучит как утка, это утка.

РЕДАКТИРОВАТЬ: Для типа None, вы можете просто сделать:

if obj is None: obj = MyClass()
fengshaun
источник
def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Это возвращает «1» вместо «Нет». Как обойти это?
dig_123 14.12.14
Если вы хотите использовать, isinstanceно проверьте, а Noneзатем isinstance(obj, (MyClass, type(None)))работает. types.NoneTypeбыл удален из Python 3, поэтому он не так переносим, type(None)чтобы получить ссылку на NoneType.
Сантери Пааволайнен
33

Во-первых, избегайте всех сравнений типов. Они очень, очень редко нужны. Иногда они помогают проверить типы параметров в функции - даже это редко. Неправильный тип данных вызовет исключение, и это все, что вам когда-либо понадобится.

Все основные функции преобразования будут отображаться как равные функции типа.

type(9) is int
type(2.5) is float
type('x') is str
type(u'x') is unicode
type(2+3j) is complex

Есть несколько других случаев.

isinstance( 'x', basestring )
isinstance( u'u', basestring )
isinstance( 9, int )
isinstance( 2.5, float )
isinstance( (2+3j), complex )

Никто, кстати, никогда не нуждается в такой проверке типов. Ни один не является единственным экземпляром NoneType. Ни один объект не является синглтоном. Просто проверьте Нет

variable is None

Кстати, не используйте вышеизложенное в целом. Используйте обычные исключения и собственный природный полиморфизм Python.

С. Лотт
источник
3
Если вы проверяете входные данные из DSL, вам нужно все это, даже NoneType. Что делать , если параметр может быть str, unicodeили None? isinstance(x, (str, unicode, types.NoneType))намного чище, чем проверять None. Если вы создаете инструменты для отложенных вычислений или собираетесь запустить длительный или ресурсоемкий процесс, очень важно typeсвоевременно обнаруживать ошибки на каком-то этапе проверки. Это была критическая часть почти каждого научного компьютерного проекта, над которым я когда-либо работал. Из всех разработок, которые я видел, это нужно больше, чем не нужно.
августа
23

Для других типов, проверьте модуль типов :

>>> import types
>>> x = "mystring"
>>> isinstance(x, types.StringType)
True
>>> x = 5
>>> isinstance(x, types.IntType)
True
>>> x = None
>>> isinstance(x, types.NoneType)
True

PS Проверка типов - плохая идея.

Паоло Бергантино
источник
15

Вы всегда можете использовать type(x) == type(y)трюк, где yесть что-то с известным типом.

# check if x is a regular string
type(x) == type('')
# check if x is an integer
type(x) == type(1)
# check if x is a NoneType
type(x) == type(None)

Часто есть лучшие способы сделать это, особенно с любым недавним питоном. Но если вы хотите запомнить только одну вещь, вы можете запомнить это.

В этом случае лучшие способы будут:

# check if x is a regular string
type(x) == str
# check if x is either a regular string or a unicode string
type(x) in [str, unicode]
# alternatively:
isinstance(x, basestring)
# check if x is an integer
type(x) == int
# check if x is a NoneType
x is None

Обратите внимание на последний случай: NoneTypeв Python есть только один экземпляр , и это так None. Вы будете часто видеть NoneType в исключениях (TypeError: 'NoneType' object is unsubscriptable - случается со мной все время ..), но вам вряд ли когда-нибудь понадобится ссылаться на него в коде.

Наконец, как указывает fengshaun, проверка типов в python не всегда хорошая идея. Более питонно просто использовать значение, как если бы оно было ожидаемым вами типом, и перехватывать (или разрешать распространять) исключения, возникающие из него.

Джон Фухи
источник
1
Для чего стоит isinstance () является предпочтительным способом проверки типов в Python (когда это необходимо сделать).
Дэвид Z
6

Ты очень близко! stringэто модуль, а не тип. Вы, вероятно, хотите сравнить тип objс объектом типа для строк, а именно str:

type(obj) == str  # this works because str is already a type

В качестве альтернативы:

type(obj) == type('')

Обратите внимание, что в Python 2, если objэто тип Unicode, то ни один из вышеперечисленных не будет работать. И не будет isinstance(). См. Комментарии Джона к этому посту, чтобы узнать, как обойти это ... Я пытался вспомнить это около 10 минут, но у меня был блок памяти!

Джаррет Харди
источник
2
Используйте базовую строку с isinstance (), чтобы получить как str, так и unicode.
Джон Фухи
5

Это потому, что вы должны написать

s="hello"
type(s) == type("")

Тип принимает экземпляр и возвращает его тип. В этом случае вы должны сравнить два типа экземпляров.

Если вам нужно сделать упреждающую проверку, лучше проверить поддерживаемый интерфейс, чем тип.

Тип на самом деле мало что говорит вам, за исключением того факта, что вашему коду нужен экземпляр определенного типа, независимо от того, что у вас может быть другой экземпляр совершенно другого типа, что было бы прекрасно, потому что он реализует тот же интерфейс ,

Например, предположим, у вас есть этот код

def firstElement(parameter):
    return parameter[0]

Теперь предположим, что вы говорите: я хочу, чтобы этот код принимал только кортеж.

import types

def firstElement(parameter):
    if type(parameter) != types.TupleType:
         raise TypeError("function accepts only a tuple")
    return parameter[0]

Это уменьшает возможность повторного использования этой процедуры. Это не сработает, если вы передадите список, или строку, или numpy.array. Что-то лучше было бы

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    return parameter[0]

но в этом нет никакого смысла: параметр [0] вызовет исключение, если протокол все равно не будет удовлетворен ... это, конечно, если вы не хотите предотвратить побочные эффекты или нет необходимости восстанавливаться после вызовов, которые вы могли бы вызвать до сбоя. (Глупый) пример, просто чтобы подчеркнуть:

def firstElement(parameter):
    if not (hasattr(parameter, "__getitem__") and callable(getattr(parameter,"__getitem__"))):
        raise TypeError("interface violation")
    os.system("rm file")
    return parameter[0]

в этом случае ваш код вызовет исключение перед выполнением вызова system (). Без проверки интерфейса вы удалили бы файл, а затем вызвали исключение.

Стефано Борини
источник
Спасибо за указание фактического предпочтительного способа проверки интерфейсов. Многие ответы здесь упоминают об этом, но лишь немногие приводят примеры того, что хорошо. Это все еще не отвечает на мой личный вопрос напрямую (я пытаюсь отделить список строк, содержащих много значимых элементов, от строки, которая содержит много не значащих элементов. Спасибо!
Ник
5

Используйте str вместо строки

type ( obj ) == str

объяснение

>>> a = "Hello"
>>> type(a)==str
True
>>> type(a)
<type 'str'>
>>>
Нил
источник
4

я использую type(x) == type(y)

Например, если я хочу проверить что-то, это массив:

type( x ) == type( [] )

проверка строки:

type( x ) == type( '' ) or type( x ) == type( u'' )

Если вы хотите проверить None, используйте

x is None
Hasen
источник
да? почему это вообще плохая идея? Это только плохая идея для строк (для версий до 3.0), потому что есть два типа строк: str и unicode. Для массивов это хорошая идея imho.
Hasen
@hasen: это плохая идея в целом. Что если я определю свой собственный тип, который ведет себя как массив, но, скажем, выбирает значения из базы данных? Ваш код потерпит неудачу с моим типом без причины.
nosklo
@hasen: прочитайте ссылку canonical.org/~kragen/isinstance с наибольшим количеством проголосовавших (+7) ответов, по voltronw
nosklo
1
Ну, вся причина (по крайней мере для меня) в проверке типа именно потому, что я хочу иметь дело с массивами иначе, чем с другими типами (включая типы, имитирующие массивы).
hasen
2
Ты не прав. Я приведу конкретный пример: в django есть ярлык для рендеринга шаблонов, который может принимать либо строку, либо массив строк. Теперь и строки, и массивы (списки) являются итеративными, но в этом случае функции должны различать их.
hasen
2

я думаю, что это должно сделать это

if isinstance(obj, str)
Азиз
источник
2

Тип не работает на определенных классах. Если вы не уверены в типе объекта, используйте __class__метод следующим образом:

>>>obj = 'a string'
>>>obj.__class__ == str
True

Также смотрите эту статью - http://www.siafoo.net/article/56

Тоби Фернслер
источник
2

Чтобы получить тип, используйте __class__член, как вunknown_thing.__class__

Разговор о наборе утки здесь бесполезен, потому что он не отвечает на совершенно хороший вопрос. В моем коде приложения мне никогда не нужно знать тип чего-либо, но все равно полезно иметь способ узнать тип объекта. Иногда мне нужно получить реальный класс для проверки модульного теста. Утиная печать мешает, потому что все возможные объекты имеют одинаковый API, но только один является правильным. Кроме того, иногда я поддерживаю чужой код и не знаю, какой тип объекта мне передали. Это моя самая большая проблема с динамически типизированными языками, такими как Python. Версия 1 очень проста и быстро разрабатывается. Версия 2 - это проблема, особенно если вы не написали версию 1. Поэтому иногда, когда я работаю с функцией, которую я не писал, мне нужно знать тип параметра,

Вот где __class__параметр пригодится. Это (насколько я могу судить) - лучший способ (возможно, единственный способ) получить тип объекта.

MiguelMunoz
источник
2

Использование isinstance(object, type). Как и выше, это легко использовать, если вы знаете правильный type, например,

isinstance('dog', str) ## gives bool True

Но для более эзотерических объектов это может быть трудно использовать. Например:

import numpy as np 
a = np.array([1,2,3]) 
isinstance(a,np.array) ## breaks

но вы можете сделать этот трюк:

y = type(np.array([1]))
isinstance(a,y) ## gives bool True 

Поэтому я рекомендую создать экземпляр переменной ( yв данном случае) с типом объекта, который вы хотите проверить (например, type(np.array())), а затем использовать isinstance.

travelingbones
источник
0

Вы можете сравнить классы для проверки уровня.

#!/usr/bin/env python
#coding:utf8

class A(object):
    def t(self):
        print 'A'
    def r(self):
        print 'rA',
        self.t()

class B(A):
    def t(self):
        print 'B'

class C(A):
    def t(self):
        print 'C'

class D(B, C):
    def t(self):
        print 'D',
        super(D, self).t()

class E(C, B):
    pass

d = D()
d.t()
d.r()

e = E()
e.t()
e.r()

print isinstance(e, D) # False
print isinstance(e, E) # True
print isinstance(e, C) # True
print isinstance(e, B) # True
print isinstance(e, (A,)) # True
print e.__class__ >= A, #False
print e.__class__ <= C, #False
print e.__class__ <  E, #False
print e.__class__ <= E  #True
quickes
источник