Python verificar se há algum tipo de instância na lista?

90

Como faço para fazer pitonicamente:

var = 7.0
var_is_good = isinstance(var, classinfo1) or isinstance(var, classinfo2) or isinstance(var, classinfo3) or ... or  isinstance(var, classinfoN)

Parece bobo, não posso simplesmente passar uma lista de informações de classe:

var_is_good = isinstanceofany( var, [classinfo1, classinfo2, ... , classinfoN] )

Então, qual é a isinstanceofanyfunção?

D Adams
fonte
Se soma como um número, subtrai como um número, multiplica como um número ... por que você precisa saber se é um número? Consulte a digitação de pato para obter mais detalhes.
Makoto
Meu caso de uso particular é ter uma função que retorna um (função que retorna (ou um numberOR ele retorna uma expressão sympy)). Quero verificar se a função que gerei faz o que deveria quando eu a passo para outras funções.
D Adams
Por que sua função não retorna algo homogêneo? Esse é o cheiro aqui; você pode ficar rápido e solto com a digitação duck, mas deve ser consistente no que retorna.
Makoto
Acho que sempre posso retornar uma expressão sympy que às vezes é avaliada como um número e às vezes tem variáveis ​​deixadas dentro dela.
D Adams
Isso é o que estou pensando que você deseja fazer aqui; em vez de retornar vários tipos diferentes, retorne um tipo e, se necessário, reduza-o a um número.
Makoto

Respostas:

200

isinstance()recebe uma tupla de classes para o segundo argumento. Ele retornará verdadeiro se o primeiro argumento for uma instância de qualquer um dos tipos nessa sequência:

isinstance(var, (classinfo1, classinfo2, classinfo3))

Em outras palavras, isinstance() oferece essa funcionalidade, fora da caixa.

Da isinstance()documentação :

Se classinfo não é um objeto de classe nem um objeto de tipo, pode ser uma tupla de objetos de classe ou de tipo, ou pode conter recursivamente outras tuplas (outros tipos de sequência não são aceitos).

Ênfase minha; observe a natureza recursiva; (classinfo1, (classinfo2, classinfo3))também é uma opção válida.

Martijn Pieters
fonte
12

Você já chegou perto do título da sua pergunta. Você pode usar anye uma lista:

var = 7.0
var_is_good = any([isinstance(var, classinfo1),
                   isinstance(var, classinfo2),
                   isinstance(var, classinfo3), ...
                   isinstance(var, classinfoN)])

Mas olhando nos documentos de isinstancerevela:

Retorne verdadeiro se o argumento do objeto for uma instância do argumento classinfo ou de uma subclasse (direta, indireta ou virtual) dele. Se o objeto não for um objeto do tipo fornecido, a função sempre retornará falso. Se classinfo não for uma classe (objeto de tipo), pode ser uma tupla de objetos de tipo ou pode conter recursivamente outras tuplas (outros tipos de sequência não são aceitos). Se classinfo não for um tipo ou tupla de tipos e tais tuplas, uma exceção TypeError é gerada.

Isso significa que a melhor maneira de fazer isso é

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))
Martin Thoma
fonte
2
Repetir isinstanceapenas com a classinfomudança não parece muito pitônico para mim.
Makoto
1
Experimente var.__class__. É isso que você quer? @Makoto: Eu concordo. Nem um pouco pitônico!
flamenco
@Makoto Yup. Mas isso era algo que D Adams provavelmente poderia ter facilmente encontrado pesquisando nos documentos por "qualquer". Expandi minha resposta para a versão melhor ... mas obviamente Martijn Pieters foi mais rápido ... mais uma vez.
Martin Thoma
3
any()com uma lista é ... inútil. Use uma expressão geradora se precisar usar any(), pelo menos você terá o benefício da saída antecipada.
Martijn Pieters
Acho que isinstancecom tupla é o melhor caminho. Eu só queria mencionar a solução com anyo que parece ser o que ele está pedindo no título.
Martin Thoma
4

Isto irá resolver o seu problema:

valid_instance_types = <tuple of types you want to allow>
var_is_good = isinstance(var, valid_instance_types)

Com base na documentação, existem várias maneiras de passar valores de tipos para isinstance.

Você também pode parecer voluptuoso se estiver tentando fazer uma validação mais complicada da qual isso seja apenas uma parte.

Nathaniel Ford
fonte
isinstance () já oferece essa funcionalidade, passe uma tupla com todos os tipos necessários para verificar como o segundo argumento
RFV
@ RFV5s Sim ... é isso que mostra o exemplo que forneci aqui. Qual é a sua objeção?
Nathaniel Ford
1

Você geralmente não deveria usar isinstance, mas o que deseja fazer pode ser realizado com a função embutida any () .

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])
Chad S.
fonte
7
Isso é um exagero; isinstance()oferece a funcionalidade pronta para uso, sem usar any().
Martijn Pieters
@MartijnPieters Não percebi que isinstance pode aceitar vários tipos, mas sinto que a resposta ainda é boa porque a pergunta pode ser considerada de forma mais ampla como "Como faço para verificar se algum dos valores de retorno de uma função específica com parâmetros diferentes é verdade "
Chad S.
Se você deve ou não usar isinstance()é irrelevante.
RFV
@ChadS. Eu gostaria de perguntar por que você acha que ele não deveria usar isinstance()? Obrigado.
idature
Porque o python evita a verificação de tipo. É muito código extra (e ciclos de CPU) para poucos benefícios. A digitação em pato é preferida.
Chad S.