Jak porównać typ obiektu w Pythonie?

163

Zasadniczo chcę to zrobić:

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

Próbowałem:

type ( obj ) == type ( string )

i to nie zadziałało.

A co z innymi typami? Na przykład nie mogłem replikować NoneType.

Joan Venge
źródło
To działatype(obj) == str
Joshua Varghese

Odpowiedzi:

241
isinstance()

W twoim przypadku isinstance("this is a string", str)wróci True.

Możesz również przeczytać to: http://www.canonical.org/~kragen/isinstance/

antoni
źródło
4
Powiedziałbym, że zdecydowanie powinieneś przeczytać odnośnik, do którego się odwołujesz, który podaje wiele szczegółów, dlaczego sprawdzanie typu obiektu jest zwykle złym pomysłem i co prawdopodobnie powinieneś zrobić zamiast tego.
Jeff Shannon
2
powinieneś użyć basestr, a nie str. w przeciwnym razie nie wybierzesz Unicode. (chociaż dla 3.x myślę, że str jest basestrem)
hasen
36

isinstance Pracuje:

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

ale pamiętaj: jeśli wygląda jak kaczka, a jeśli brzmi jak kaczka, to jest to kaczka.

EDYCJA: W przypadku typu Brak możesz po prostu wykonać:

if obj is None: obj = MyClass()
fengshaun
źródło
def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Zwraca „1” zamiast „Nie”. Jak to obejść?
dig_123
Jeśli chcesz użyć isinstanceale sprawdź również dla Noneówczesnych isinstance(obj, (MyClass, type(None)))dzieł. types.NoneTypezostał usunięty z Pythona 3, więc nie jest tak przenośny, jak type(None)uzyskanie odniesienia do NoneType.
Santeri Paavolainen
33

Po pierwsze, unikaj wszelkich porównań typów. Są bardzo, bardzo rzadko potrzebne. Czasami pomagają sprawdzić typy parametrów w funkcji - nawet to rzadkie. Dane nieprawidłowego typu spowodują wyjątek, a to wszystko, czego kiedykolwiek będziesz potrzebować.

Wszystkie podstawowe funkcje konwersji będą mapowane jako równe funkcji typu.

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

Jest kilka innych przypadków.

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

Żaden, BTW, nigdy nie wymaga tego rodzaju kontroli. None jest jedynym wystąpieniem NoneType. Obiekt None jest singletonem. Po prostu zaznacz opcję Brak

variable is None

Przy okazji, nie używaj powyższego ogólnie. Użyj zwykłych wyjątków i własnego naturalnego polimorfizmu Pythona.

S.Lott
źródło
3
Jeśli sprawdzasz poprawność danych wejściowych z DSL, potrzebujesz tego wszystkiego NoneType. Co jeśli parametr może być str, unicodealbo None? isinstance(x, (str, unicode, types.NoneType))jest znacznie czystszy niż sprawdzanie None. Jeśli tworzysz narzędzia do odroczonych obliczeń lub jeśli masz zamiar uruchomić długi lub wymagający dużej ilości zasobów proces, warto wychwycić typebłędy z wyprzedzeniem, podczas niestandardowego kroku weryfikacji. To była kluczowa część prawie każdego naukowego projektu komputerowego, nad którym kiedykolwiek pracowałem. Ze wszystkich projektów deweloperskich, jakie widziałem, więcej tego potrzebowało niż nie.
ely
23

W przypadku innych typów sprawdź moduł typów :

>>> 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 to zły pomysł.

Paolo Bergantino
źródło
15

Zawsze możesz użyć type(x) == type(y)sztuczki, gdzie yjest coś o znanym typie.

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

Często istnieją lepsze sposoby na zrobienie tego, szczególnie w przypadku dowolnego nowego Pythona. Ale jeśli chcesz zapamiętać tylko jedną rzecz, możesz to zapamiętać.

W takim przypadku lepszym sposobem byłoby:

# 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

Zwróć uwagę na ostatni przypadek: NoneTypew pythonie jest tylko jedno wystąpienie None. Zobaczysz NoneType w wyjątkach ( TypeError: 'NoneType' object is unsubscriptable- zdarza mi się cały czas ...), ale prawie nigdy nie będziesz musiał odnosić się do tego w kodzie.

Wreszcie, jak zauważa fengshaun, sprawdzanie typów w Pythonie nie zawsze jest dobrym pomysłem. Bardziej pythonowe jest po prostu użycie wartości tak, jakby była to oczekiwany typ i wyłapywanie (lub pozwolenie na propagację) wyjątków, które z niej wynikają.

John Fouhy
źródło
1
Warto wiedzieć, że isinstance () jest preferowanym sposobem sprawdzania typów w Pythonie (kiedy trzeba to zrobić).
David Z
6

Jesteś już blisko! stringjest modułem, a nie typem. Prawdopodobnie chcesz porównać typ z objobiektem typu dla ciągów, a mianowicie str:

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

Alternatywnie:

type(obj) == type('')

Uwaga, w Pythonie 2, jeśli objjest to typ Unicode, żadne z powyższych nie będzie działać. Ani nie będzie isinstance(). Zobacz komentarze Johna do tego posta, aby dowiedzieć się, jak to obejść ... Próbowałem to sobie przypomnieć od około 10 minut, ale miałem blok pamięci!

Jarret Hardie
źródło
2
Użyj basestring z isinstance (), aby uzyskać zarówno str, jak i unicode.
John Fouhy
5

To dlatego, że musisz pisać

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

type akceptuje instancję i zwraca jej typ. W takim przypadku musisz porównać typy dwóch instancji.

Jeśli chcesz przeprowadzić sprawdzanie zapobiegawcze, lepiej jest sprawdzić obsługiwany interfejs niż typ.

Typ tak naprawdę nie mówi ci wiele, poza tym, że twój kod potrzebuje instancji określonego typu, niezależnie od tego, że możesz mieć inną instancję zupełnie innego typu, co byłoby całkowicie w porządku, ponieważ implementuje ten sam interfejs .

Na przykład załóżmy, że masz ten kod

def firstElement(parameter):
    return parameter[0]

Teraz przypuśćmy, że powiesz: chcę, aby ten kod akceptował tylko krotkę.

import types

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

Zmniejsza to możliwość ponownego wykorzystania tej procedury. Nie zadziała, jeśli przekażesz listę, ciąg znaków lub numpy.array. Coś lepszego byłoby

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

ale nie ma sensu to robić: parametr [0] zgłosi wyjątek, jeśli protokół i tak nie jest spełniony ... to oczywiście, chyba że chcesz zapobiec efektom ubocznym lub musisz odzyskać kontrolę po wywołaniach, które możesz wywołać przed niepowodzeniem. (Głupi) przykład, żeby podkreślić:

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

w tym przypadku twój kod zgłosi wyjątek przed uruchomieniem wywołania system (). Bez sprawdzenia interfejsu usunąłbyś plik, a następnie zgłosił wyjątek.

Stefano Borini
źródło
Dziękujemy za wskazanie faktycznego preferowanego sposobu sprawdzania interfejsów. Wiele odpowiedzi tutaj o tym wspomina, ale niewiele z nich podaje przykłady tego, co jest dobre. Nadal nie odpowiada bezpośrednio na moje osobiste pytanie (próbuję oddzielić listę ciągów zawierających wiele znaczących elementów od ciągu zawierającego wiele nieistotnych elementów. Dzięki!
Nick
5

Użyj str zamiast string

type ( obj ) == str

Wyjaśnienie

>>> a = "Hello"
>>> type(a)==str
True
>>> type(a)
<type 'str'>
>>>
Neil
źródło
4

używam type(x) == type(y)

Na przykład, jeśli chcę sprawdzić, czy coś jest tablicą:

type( x ) == type( [] )

sprawdzenie ciągów:

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

Jeśli chcesz sprawdzić, czy nie ma wartości None, użyj is

x is None
hasen
źródło
co? dlaczego jest to ogólnie zły pomysł? To zły pomysł tylko w przypadku stringów (w wersjach wcześniejszych niż 3.0), ponieważ istnieją dwa typy łańcuchów, str i unicode. W przypadku tablic imho to dobry pomysł.
hasen
@hasen: to ogólnie zły pomysł. Co się stanie, jeśli zdefiniuję własny typ, który zachowuje się jak tablica, ale, powiedzmy, pobiera wartości z bazy danych? Twój kod zawiedzie z moim typem bez powodu.
nosklo
@hasen: przeczytaj link canonical.org/~kragen/isinstance z najczęściej głosowaną (+7) odpowiedzią, autor: voltronw
nosklo
1
Cóż, cały powód (przynajmniej dla mnie) przy sprawdzaniu typu jest dokładnie taki, że chcę radzić sobie z tablicami inaczej niż inne typy (w tym typy imitujące tablice).
hasen
2
Jesteś w błędzie. Podam konkretny przykład: django ma skrót do renderowania szablonu, który może akceptować ciąg znaków lub tablicę ciągów. Teraz zarówno łańcuchy, jak i tablice (listy) są iterowalne, ale w tym przypadku funkcje muszą je rozróżniać.
hasen
2

myślę, że to powinno wystarczyć

if isinstance(obj, str)
Aziz
źródło
2

Typ nie działa na niektórych klasach. Jeśli nie masz pewności co do typu obiektu, skorzystaj z __class__metody:

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

Zobacz także ten artykuł - http://www.siafoo.net/article/56

Toby Fernsler
źródło
2

Aby uzyskać typ, użyj elementu __class__członkowskiego, jak wunknown_thing.__class__

Mówienie o pisaniu na klawiaturze jest tu bezużyteczne, ponieważ nie odpowiada na całkiem dobre pytanie. W moim kodzie aplikacji nigdy nie muszę znać typu czegoś, ale wciąż przydatna jest możliwość nauczenia się typu obiektu. Czasami potrzebuję uzyskać rzeczywistą klasę, aby zweryfikować test jednostkowy. Duck typing staje na przeszkodzie, ponieważ wszystkie możliwe obiekty mają to samo API, ale tylko jeden jest poprawny. Poza tym czasami zajmuję się cudzym kodem i nie mam pojęcia, jaki obiekt został mi przekazany. To jest mój największy problem z dynamicznie wpisywanymi językami, takimi jak Python. Wersja 1 jest bardzo łatwa i szybka w opracowaniu. Wersja 2 jest uciążliwa, zwłaszcza jeśli nie napisałeś wersji 1. Więc czasami, gdy pracuję z funkcją, której nie napisałem, muszę znać typ parametru,

Tutaj __class__przydaje się parametr. To (o ile wiem) najlepszy sposób (może jedyny) na uzyskanie typu obiektu.

MiguelMunoz
źródło
2

Użyj isinstance(object, type). Jak wyżej, jest to łatwe w użyciu, jeśli znasz poprawną type, np.

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

Ale w przypadku bardziej ezoterycznych obiektów może to być trudne w użyciu. Na przykład:

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

ale możesz zrobić tę sztuczkę:

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

Dlatego zalecam utworzenie instancji zmiennej ( yw tym przypadku) z typem obiektu, który chcesz sprawdzić (np. type(np.array())), A następnie użycie isinstance.

kości podróżne
źródło
0

Możesz porównać klasy, aby sprawdzić poziom.

#!/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
szybkie
źródło