Como comparar o tipo de um objeto em Python?

163

Basicamente, quero fazer isso:

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

Eu tentei:

type ( obj ) == type ( string )

e não funcionou.

Além disso, e os outros tipos? Por exemplo, não consegui replicar NoneType.

Joan Venge
fonte
Isso funcionatype(obj) == str
Joshua Varghese

Respostas:

241
isinstance()

No seu caso, isinstance("this is a string", str)retornará True.

Você também pode ler isto: http://www.canonical.org/~kragen/isinstance/

anthony
fonte
4
Eu diria que você (o OP) deve ler definitivamente o link referenciado, o que fornece muitos detalhes sobre por que verificar o tipo de um objeto geralmente é uma má idéia e o que você provavelmente deveria estar fazendo.
10119 Jeff Shannon
2
você deve usar basestr, não str. caso contrário, você não escolherá unicode. (embora para 3.x Acho que str é o basestr)
Hasen
36

isinstance trabalho:

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

mas lembre-se: se parece um pato e se parece com um pato, é um pato.

EDIT: Para o tipo None, você pode simplesmente fazer:

if obj is None: obj = MyClass()
fengshaun
fonte
def distance_from_zero(n): if isinstance(n,int) or isinstance(n,float): return abs(n) else: return "Nope" print distance_from_zero(True) Isso retorna um "1" em vez de "Nope". Como contornar isso?
dig_123
Se você deseja usar, isinstancemas verifique também para None, em seguida, isinstance(obj, (MyClass, type(None)))funciona. types.NoneTypefoi removido do Python 3, portanto, não é tão portátil quanto type(None)obter uma referência NoneType.
Santeri Paavolainen
33

Primeiro, evite todas as comparações de tipos. Eles são muito, muito raramente necessários. Às vezes, eles ajudam a verificar os tipos de parâmetros em uma função - mesmo que isso seja raro. Dados de tipo errado geram uma exceção e é tudo o que você precisa.

Todas as funções básicas de conversão serão mapeadas como iguais à função type.

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

Existem alguns outros casos.

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

Nenhum, BTW, nunca precisa desse tipo de verificação de tipo. Nenhuma é a única instância de NoneType. O objeto None é um Singleton. Basta verificar Nenhum

variable is None

BTW, não use o descrito acima em geral. Use exceções comuns e o polimorfismo natural do próprio Python.

S.Lott
fonte
3
Se você estiver validando entradas de uma DSL, precisará de tudo isso, inclusive NoneType. E se um parâmetro pode ser um str, unicodeou None? isinstance(x, (str, unicode, types.NoneType))é muito mais limpo do que procurar None. Se você estiver construindo ferramentas para computação adiada ou se estiver prestes a iniciar um processo longo ou com muitos recursos, é importante detectar typeerros com antecedência, durante alguma etapa de validação personalizada. Essa foi uma parte crítica de quase todos os projetos de computação científica em que já trabalhei. De todos os projetos de desenvolvimento que eu já vi, mais precisam disso do que não.
Ely
23

Para outros tipos, consulte o módulo de tipos :

>>> 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 é uma má idéia.

Paolo Bergantino
fonte
15

Você sempre pode usar o type(x) == type(y)truque, onde yhá algo com tipo conhecido.

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

Muitas vezes, existem maneiras melhores de fazer isso, principalmente em qualquer python recente. Mas se você quer apenas se lembrar de uma coisa, pode se lembrar disso.

Nesse caso, as melhores maneiras seriam:

# 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

Observe o último caso: existe apenas uma instância de NoneTypeem python, e é isso None. Você verá o NoneType muito em exceções ( TypeError: 'NoneType' object is unsubscriptable- acontece comigo o tempo todo ..), mas quase nunca precisará se referir a ele no código.

Finalmente, como fengshaun aponta, a verificação de tipo no python nem sempre é uma boa ideia. É mais pitônico usar apenas o valor como se fosse o tipo que você espera e capturar (ou permitir propagar) exceções resultantes dele.

John Fouhy
fonte
1
Pelo que vale, isinstance () é a maneira preferida de verificar tipos em Python (quando você precisar fazer isso).
David Z
6

Você está muito perto! stringé um módulo, não um tipo. Você provavelmente deseja comparar o tipo de objcom o objeto de tipo de strings, a saber str:

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

Alternativamente:

type(obj) == type('')

Observe que, no Python 2, se objfor do tipo unicode, nenhuma das opções acima funcionará. Nem vai isinstance(). Veja os comentários de John neste post para saber como contornar isso ... Estou tentando lembrá-lo há cerca de 10 minutos, mas estava com um bloco de memória!

Jarret Hardie
fonte
2
Use basestring com isinstance () para obter str e unicode.
31410 John Fouhy
5

É porque você tem que escrever

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

type aceita uma instância e retorna seu tipo. Nesse caso, você deve comparar os tipos de duas instâncias.

Se você precisar fazer uma verificação preventiva, é melhor verificar se há uma interface suportada do que o tipo.

O tipo realmente não diz muito, além do fato de que seu código deseja uma instância de um tipo específico, independentemente do fato de que você poderia ter outra instância de um tipo completamente diferente, o que seria perfeitamente adequado porque implementa a mesma interface .

Por exemplo, suponha que você tenha esse código

def firstElement(parameter):
    return parameter[0]

Agora, suponha que você diga: quero que esse código aceite apenas uma tupla.

import types

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

Isso está reduzindo a reutilização dessa rotina. Não funcionará se você passar uma lista, uma string ou um numpy.array. Algo melhor seria

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

mas não adianta fazê-lo: o parâmetro [0] gerará uma exceção se o protocolo não for atendido de qualquer maneira ... é claro, a menos que você queira evitar efeitos colaterais ou se recuperar de chamadas que você poderia chamar antes de falhar. Exemplo (estúpido), apenas para deixar claro:

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

nesse caso, seu código gerará uma exceção antes de executar a chamada system (). Sem verificações de interface, você teria removido o arquivo e, em seguida, levantado a exceção.

Stefano Borini
fonte
Obrigado por indicar a maneira preferida real de verificar interfaces. Muitas das respostas aqui mencionam isso, mas poucas dão exemplos do que é bom. Ele ainda não respondeu à minha pergunta pessoal diretamente (eu estou tentando separar uma lista de strings, contendo muitos, itens significativos, a partir de uma string, que contém muitos, e não itens significativos Graças.!
Nick
5

Use str em vez de string

type ( obj ) == str

Explicação

>>> a = "Hello"
>>> type(a)==str
True
>>> type(a)
<type 'str'>
>>>
Neil
fonte
4

eu uso type(x) == type(y)

Por exemplo, se eu quiser verificar algo é uma matriz:

type( x ) == type( [] )

verificação de cadeia:

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

Se você deseja verificar Nenhum, use

x is None
hasen
fonte
Hã? por que é uma má ideia em geral? É apenas uma péssima idéia para strings (para a versão 3.0), porque existem dois tipos de strings, str e unicode. Para matrizes, é uma boa ideia imho.
hasen
@ hasen: é uma má ideia em geral. E se eu definir meu próprio tipo que se comporte como uma matriz, mas, digamos, buscar valores de um banco de dados? Seu código falhará com meu tipo sem motivo.
Nosklo 03/04/09
@hasen: leia no link canonical.org/~kragen/isinstance do mais votado (+7) resposta, por voltronw
nosklo
1
Bem, todo o motivo (pelo menos para mim) na verificação do tipo é exatamente porque eu quero lidar com matrizes de maneira diferente de outros tipos (incluindo tipos que imitam matrizes).
hasen
2
Você está errado. Vou dar um exemplo concreto: o django possui um atalho de renderização de modelo que pode aceitar uma string ou uma matriz de strings. Agora, as seqüências de caracteres e as matrizes (listas) são iteráveis, mas, neste caso, as funções precisam diferenciar entre elas.
hasen
2

eu acho que isso deve fazer

if isinstance(obj, str)
Aziz
fonte
2

Tipo não funciona em determinadas classes. Se você não tiver certeza do tipo do objeto, use o __class__método da seguinte maneira:

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

Consulte também este artigo - http://www.siafoo.net/article/56

Toby Fernsler
fonte
2

Para obter o tipo, use o __class__membro, como emunknown_thing.__class__

Falar em digitar patos é inútil aqui, porque não responde a uma pergunta perfeitamente boa. No código do meu aplicativo, nunca preciso saber o tipo de algo, mas ainda é útil ter uma maneira de aprender o tipo de um objeto. Às vezes, preciso obter a turma real para validar um teste de unidade. A digitação com patos atrapalha o caminho porque todos os objetos possíveis têm a mesma API, mas apenas um está correto. Além disso, às vezes estou mantendo o código de outra pessoa e não tenho idéia de que tipo de objeto fui passado. Este é o meu maior problema com linguagens dinamicamente tipadas como Python. A versão 1 é muito fácil e rápida de desenvolver. A versão 2 é uma chatice, especialmente se você não escreveu a versão 1. Então, às vezes, quando estou trabalhando com uma função que não escrevi, preciso saber o tipo de parâmetro,

É aí que o __class__parâmetro é útil. Essa (até onde eu sei) é a melhor maneira (talvez a única) de obter o tipo de um objeto.

MiguelMunoz
fonte
2

Use isinstance(object, type). Como acima, isso é fácil de usar se você souber o correto type, por exemplo,

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

Mas para objetos mais esotéricos, isso pode ser difícil de usar. Por exemplo:

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

mas você pode fazer este truque:

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

Portanto, recomendo instanciar uma variável ( yneste caso) com um tipo de objeto que você deseja verificar (por exemplo, type(np.array())) e depois usá-lo isinstance.

travelbones
fonte
0

Você pode comparar as classes para o nível de verificação.

#!/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
fonte