Em python, qual é a melhor maneira de testar se uma variável contém uma lista ou uma tupla? (ou seja, uma coleção)
É isinstance()
tão mau como sugerido aqui? http://www.canonical.org/~kragen/isinstance/
Atualização: a razão mais comum pela qual desejo distinguir uma lista de uma string é quando tenho uma estrutura de árvore / dados aninhada indefinidamente profunda de listas de listas de listas de strings etc. que estou explorando com um algoritmo recursivo e preciso para saber quando atingi os nós da "folha".
Respostas:
Vá em frente e use
isinstance
se precisar. É um tanto ruim, pois exclui sequências personalizadas, iteradores e outras coisas que você realmente pode precisar. No entanto, às vezes você precisa se comportar de maneira diferente se alguém, por exemplo, passa uma string. Minha preferência seria verificar explicitamentestr
ou algounicode
assim:NB Não confunda
types.StringType
comtypes.StringTypes
. Este último incorporastr
eunicode
objeta.O
types
módulo é considerado por muitos obsoleto em favor de apenas verificar diretamente o tipo de objeto; portanto, se você preferir não usar o acima, pode alternativamente verificar explicitamente contrastr
eunicode
, assim:Editar:
Melhor ainda é:
Finalizar edição
Depois de qualquer uma dessas opções, você pode voltar a se comportar como se estivesse obtendo uma sequência normal, permitindo que as não-sequências gerem exceções apropriadas.
Ver o que é "mau" na verificação de tipos não é que você queira se comportar de maneira diferente para um determinado tipo de objeto, é que você restringe artificialmente sua função de fazer a coisa certa com tipos de objetos inesperados que, de outra forma, fariam a coisa certa. Se você tiver um fallback final que não é verificado por tipo, remova essa restrição. Deve-se observar que muita verificação de tipo é um cheiro de código que indica que você pode querer refatorar, mas isso não significa necessariamente que você deve evitá-la do getgo.
fonte
str
tipo, basta usá-lo diretamente, em vez de usartypes.StringType
qual é apenas um alias para ele. Mas não acho que essa resposta responda à pergunta, pois se tratava de "uma coleção". A menos que você esteja usando um python novo o suficiente para ter oabc
módulo que não é algo que possa serisinstance
verificado, e mesmo assim eu recomendaria evitar a verificação, se possível.assert isinstance(u'abc', str) == False
. Concordo que é melhor verificar diretamente com o tipo, em vez de usar otypes
módulo, mastypes.StringTypes
faz algo questr
não faz: retorna True parastr
eunicode
objetos. Vou editar minha resposta para oferecer uma verificação dupla como alternativa.isinstance
mau?" E dei um contra-exemplo, do qual (1) é um uso não-mauisinstance
, porque ter um fallback significa que não quebra o tipo de pato e (2) é uma boa solução para uma motivação muito comum que as pessoas têm por querer verificar se algo é umlist
outuple
( ou seja, para desambiguá-los das strings).class Foo(str): pass
que você quer?fonte
type([]) is list
retornosTrue
type(x) in [list,tuple]
é mais curto.Não há nada errado em usar
isinstance
, desde que não seja redundante. Se uma variável deve ser apenas uma lista / tupla, documente a interface e use-a como tal. Caso contrário, um cheque é perfeitamente razoável:Esse tipo de verificação possui alguns bons casos de uso, como com a sequência padrão beginwith / endswith methods (embora, para ser preciso, eles sejam implementados em C no CPython, usando uma verificação explícita para verificar se é uma tupla - há mais de uma maneira para resolver esse problema, conforme mencionado no artigo ao qual você vincula).
Uma verificação explícita geralmente é melhor do que tentar usar o objeto como um contêiner e manipular a exceção - isso pode causar todos os tipos de problemas com o código sendo executado parcial ou desnecessariamente.
fonte
set
objeto também é iterável, o que significa que, embora você possa seguramente extrair elementos dele, mas não garante uma determinada ordem, o que é uma coisa muito perigosa para certos algoritmos. Nos casos em que a ordem dos elementos é importante, um algoritmo usando esse snippet pode gerar resultados diferentes em execuções diferentes!Documente o argumento como precisando ser uma sequência e use-o como uma sequência. Não verifique o tipo.
fonte
Que tal
hasattr(a, "__iter__")
:?Informa se o objeto retornado pode ser iterado como um gerador. Por padrão, tuplas e listas podem, mas não os tipos de sequência.
fonte
__iter__
.__iter__
por algum motivo ...Nos
type(list) is list
retornos do Python 2.8false
, sugiro comparar o tipo dessa maneira horrível:
(pelo menos no meu sistema, usando anaconda no Mac OS X Yosemite)
fonte
type(list) is list
retornaFalse
porquetype(list)
étype
, nãolist
.type(list()) is list
ou com qualquer outra instância de uma lista retornaráTrue
.Python usa "digitação de pato", ou seja, se uma variável kwaks como um pato, deve ser um pato. No seu caso, você provavelmente deseja que seja iterável ou deseja acessar o item em um determinado índice. Você deve fazer o seguinte: ou seja, usar o objeto dentro
for var:
ouvar[idx]
dentro de umtry
bloco e, se você receber uma exceção, não era um pato ...fonte
var
uma iteração de sequência ocorrerá com resultados provavelmente inesperados.fonte
Se você só precisa saber se pode usar a
foo[123]
notação com a variável, pode verificar a existência de um__getitem__
atributo (que é o que python chama quando você acessa por índice) comhasattr(foo, '__getitem__')
fonte
Tem que ser um teste mais complexo se você realmente quiser lidar com praticamente qualquer coisa como argumento de função.
Embora, geralmente seja suficiente apenas especificar que uma função espera iterável e depois verificar apenas
type(a) != type('')
.Também pode acontecer que, para uma string, você tenha um caminho de processamento simples ou que seja legal e faça uma divisão etc., para que não queira gritar com strings e se alguém lhe enviar algo estranho, deixe uma exceção.
fonte
Outra maneira fácil de descobrir se uma variável é lista ou tupla ou geralmente verifica o tipo de variável seria:
fonte
Em princípio, concordo com Ignacio, acima, mas você também pode usar o tipo para verificar se algo é uma tupla ou uma lista.
fonte