Determinar o tipo de objecto?

Existe uma maneira simples de determinar se uma variável é uma lista, dicionário, ou algo mais? Estou recebendo um objeto de volta que pode ser qualquer tipo e eu preciso ser capaz de dizer a diferença.

 1441
Author: martineau, 2010-02-09

9 answers

Para obter o tipo de objeto, você pode usar o embutido type() função. Passando um objeto como o único parâmetro irá retornar o tipo de objeto desse objeto:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>

Isto também funciona para tipos personalizados:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Note que type() só irá devolver o tipo imediato do objecto, mas não será capaz de lhe falar sobre herança tipo.

>>> type(b) is Test1
False

Para cobrir isso, deve usar o isinstance função. É claro que isto também funciona para tipos incorporados:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() é geralmente a maneira preferida de garantir o tipo de um objeto porque ele também aceitará tipos derivados. Então, a menos que você realmente precise do objeto tipo (por qualquer razão), usar isinstance() é preferido sobre type().

O segundo parâmetro de {[8] } também aceita uma tupla de tipos, por isso é possível verificar vários tipos de uma vez. isinstance então retornará verdadeiro, se o objeto for de algum desses tipos:

>>> isinstance([], (tuple, list, set))
True
 1658
Author: poke, 2014-12-19 15:17:28

Podes fazer isso usando type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>
 146
Author: inkedmn, 2010-02-08 21:39:17

Pode ser mais Pythonic usar um {[[0]}...Bloco. Dessa forma, se você tiver uma classe que grasna como uma lista, ou grasna como uma dict, ela se comportará corretamente independentemente do que seu tipo realmente é.

Para esclarecer, o método preferido de "dizer a diferença" entre os tipos variáveis é com algo chamado duck typing : desde que os métodos (e tipos de retorno) a que uma variável responde sejam o que a sua sub-rotina espera, trate - o como você espera que seja. Por exemplo, se você tem uma classe que sobrecarrega os operadores de suporte com {[[2]} e setattr, mas usa algum esquema interno engraçado, seria apropriado que ele se comportasse como um dicionário, se é isso que ele está tentando imitar.

O outro problema com a verificação de type(A) is type(B) é que se A é uma subclasse de B, ele avalia para false quando, programaticamente, você esperaria que fosse true. Se um objeto é uma subclasse de uma lista, ele deve funcionar como uma lista: o tipo apresentado na outra resposta evitará isso. ([[9]} funcionará, no entanto).

 38
Author: Seth Johnson, 2010-02-09 16:56:49

Em instâncias de objeto você também tem o:

__class__

Atributo. Aqui está uma amostra retirada da consola do Python 3.3

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Cuidado com isso no python 3.as classes x e New-Style (aviable opcionalmente a partir do Python 2.6) foram fundidas e isso pode levar a resultados inesperados. Principalmente por esta razão, a minha forma favorita de testar tipos / classes é a isinstance construída na função.

 32
Author: Lorenzo Persichetti, 2013-06-26 21:38:42

Determinar o tipo de um objecto Python

Determinar o tipo de objecto com type

>>> obj = object()
>>> type(obj)
<class 'object'>

Apesar de funcionar, evite atributos duplos como __class__ - eles não são semanticamente públicos, e, embora talvez não neste caso, as funções de construção geralmente têm um melhor comportamento.

>>> obj.__class__ # avoid this!
<class 'object'>

Verificação do tipo

Existe uma maneira simples de determinar se uma variável é uma lista, dicionário, ou algo mais? Estou a recuperar um objecto que pode ser qualquer um dos tipos e eu preciso ser capaz de dizer a diferença.

Bem, essa é uma pergunta diferente, não use o tipo de uso.isinstance:
def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

Isto cobre o caso em que o seu utilizador pode estar a fazer algo inteligente ou sensato subclassificando {[[8]} - de acordo com o princípio da substituição de Liskov, você quer ser capaz de usar subclass instâncias sem quebrar o seu código - e isinstance apoia isto.

Usar As Abstracções

Ainda melhor, podes procurar uma classe de base abstracta específica de collections ou numbers:
from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

Ou não Digitas explicitamente a verificação

Ou, talvez o melhor de tudo, use a datilografia de pato, e não digite explicitamente o seu código. A datilografia de patos suporta a substituição de Liskov com mais elegância e menos verbosidade.
def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

Conclusão

  • usar type para realmente obter a classe de uma instância.
  • usar isinstance para verificar explicitamente as subclasses reais ou as abstracções registadas.
  • e apenas evite o tipo de verificação onde faz sentido.
 15
Author: Aaron Hall, 2017-03-14 21:12:16

Pode utilizar type() ou isinstance().

>>> type([]) is list
True

Esteja avisado que pode bater list ou qualquer outro tipo atribuindo uma variável no âmbito actual do mesmo nome.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

Acima vemos que dict é transferido para uma cadeia, portanto o teste:

type({}) is dict

...falha.

Para contornar isto e utilizar {[4] } mais cuidadosamente:

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True
 11
Author: deed02392, 2014-05-31 21:57:27

Enquanto as perguntas são muito antigas, eu tropecei nisto enquanto descobria uma maneira própria, e acho que ainda precisa de ser esclarecida, pelo menos para o Python 2.x (não verificou o Python 3, mas como a questão surge com classes clássicas que se foram em tal versão, provavelmente não importa).

Aqui estou eu a tentar responder à pergunta do título: Como posso determinar o tipo de um objecto arbitrário ? Outras sugestões sobre usar ou não usar isinstance são muito bem em muitos comentários e respostas, mas não estou a responder a essas preocupações.

O principal problema com a abordagem type() é que não funciona adequadamente com instâncias de estilo antigo.:

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

Executar este excerto renderia:

Are o and t instances of the same class? True
O que, eu diria, não é o que a maioria das pessoas esperaria.

A abordagem __class__ é a mais próxima da correcção, mas não funcionará num caso crucial: quando o objecto aprovado é um antigo estilo classe (não um exemplo!), uma vez que esses objetos não possuem tal atributo.

Este é o mais pequeno trecho de código que eu poderia pensar que satisfaz essa pergunta legítima de uma forma consistente: {[[9]}
#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type
 4
Author: Alan Franzoni, 2016-06-17 08:35:20
Como um aparte das respostas anteriores, vale a pena mencionar a existência de collections.abc que contém várias classes abstratas de base (ABCs) que complementam a datilografia de patos.

Por exemplo, em vez de verificar explicitamente se algo é uma lista com:

isinstance(my_obj, list)

Você poderia, se você só está interessado em ver se o objeto que você tem permite obter itens, use collections.abc.Sequence:

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

Se você está estritamente interessado em objetos que permitem obter, definir e apagar itens (i. e. sequências mutáveis), Você optaria por collections.abc.MutableSequence.

Muitos outros ABCs são definidos lá, Mapping para objectos que podem ser usados como mapas, Iterable, Callable, etc. Uma lista completa de todos estes pode ser vista em a documentação para collections.abc.

 3
Author: Jim Fasarakis Hilliard, 2016-12-07 15:50:37

Tenha cuidado com isinstance

isinstance(True, bool)
True
>>> isinstance(True, int)
True

Mas Tipo

type(True) == bool
True
>>> type(True) == int
False
 3
Author: Mr.Green, 2017-11-14 11:22:11