Як порівняти тип об’єкта в 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()

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" замість "Nope". Як обійти це?
dig_123

Якщо ви хочете використовувати , isinstanceале перевірити також Noneтоді isinstance(obj, (MyClass, type(None)))працює. types.NoneTypeбуло видалено з Python 3, тому він не настільки портативний, type(None)щоб отримати посилання на нього NoneType.
Santeri Paavolainen

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 )

Жодна, BTW, ніколи не потребує будь-якого подібного типу перевірки. Жоден не є єдиним екземпляром NoneType. Об'єкт None - це Singleton. Просто перевірте наявність "None"

variable is None

До речі, не використовуйте вищезазначене. Використовуйте звичайні винятки та власний природний поліморфізм Пітона.


3
Якщо ви перевіряєте вхідні дані від DSL, вам потрібно все це навіть NoneType. Що робити , якщо параметр може бути str, unicodeабо None? isinstance(x, (str, unicode, types.NoneType))набагато чистіше, ніж перевірка None. Якщо ви створюєте інструменти для відкладених обчислень або збираєтеся запустити тривалий або ресурсомісткий процес, важливо typeзаздалегідь вловлювати помилки під час певного етапу перевірки. Це було важливою частиною майже кожного наукового обчислювального проекту, над яким я коли-небудь працював. З усіх розроблених проектів розробників, мені більше було потрібно, ніж ні.
ely

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 Typechecking - це погана ідея.


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 (коли це потрібно зробити).
David 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
Використовуйте basestring з isinstance (), щоб отримати і str, і unicode.
Джон Фухі

5

Це тому, що треба писати

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

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]

у цьому випадку ваш код підніме виняток перед запуском системного () виклику. Без перевірки інтерфейсу ви видалили б файл і потім підняли виняток.


Дякуємо, що вказали на бажаний спосіб перевірити наявність інтерфейсів. Багато відповідей тут згадують, але мало хто наводить приклади того, що добре. Він все ще не відповідає безпосередньо на моє особисте запитання (я намагаюся відокремити список рядків, що містять багато змістовних елементів, від рядка, який містить багато, не значущих елементів. Дякую!
Нік,

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'' )

Якщо ви хочете перевірити "Немає", скористайтеся

x is None

так? чому це взагалі погана ідея? Це лише погана ідея для рядків (для попереднього 3.0), оскільки існує два типи рядків, str та unicode. Для масивів це гарна ідея imho.
hasen

@hasen: в цілому це погана ідея. Що робити, якщо я визначаю власний тип, який веде себе як масив, але, скажімо, отримує значення з бази даних? Ваш код не зникне з моїм типом без жодної причини.
nosklo

@hasen: прочитайте посилання canonical.org/~kragen/isinstan з найбільш голосової (+7) відповіді, від voltronw
nosklo

1
Ну, вся причина (як мінімум, для мене) перевірка типу саме в тому, що я хочу мати справу з масивами інакше, ніж з іншими типами (включаючи типи, що імітують масиви).
hasen

2
Ви помиляєтеся. Наведу конкретний приклад: у django є ярлик швидкого відображення шаблону, який може приймати або рядок, або масив рядків. Тепер і рядки, і масиви (списки) є ітерабельними, але в цьому випадку функції потрібно диференціювати між ними.
hasen



2

Щоб отримати тип, використовуйте __class__член, як уunknown_thing.__class__

Говорити про типи качок тут марно, оскільки це не дає відповіді на дуже гарне запитання. У своєму коді програми мені ніколи не потрібно знати тип чогось, але все-таки корисно мати спосіб дізнатися тип об’єкта. Іноді мені потрібно отримати власне клас для перевірки одиничного тесту. Введення качок перешкоджає туди, оскільки всі можливі об'єкти мають однаковий API, але лише один є правильним. Крім того, іноді я зберігаю чужий код, і я не маю уявлення, який саме об’єкт мені передали. Це моя найбільша проблема з динамічно набраними мовами, такими як Python. Версія 1 дуже легко та швидко розробляється. Версія 2 - це біль у булочках, особливо якщо ви не писали версію 1. Тому іноді, коли я працюю з функцією, яку я не писав, мені потрібно знати тип параметра,

Ось тут __class__параметр стане у нагоді. Це (наскільки я можу сказати) - найкращий спосіб (можливо, єдиний спосіб) отримати тип об'єкта.


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.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.