Python sprawdza, czy instancja jest na liście?

87

Jak to zrobić w Pythonie:

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

Wydaje się głupie, że nie mogę po prostu przekazać listy informacji klasowych:

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

Więc jaka jest isinstanceofanyfunkcja?

D Adams
źródło
Jeśli dodaje jak liczba, odejmuje jak liczbę, mnoży jak liczbę… dlaczego musisz wiedzieć, czy to liczba? Aby uzyskać więcej informacji, zobacz wpisywanie kaczek .
Makoto,
Moim szczególnym przypadkiem użycia jest funkcja, która zwraca (funkcję, która zwraca (albo numberLUB, zwraca wyrażenie sympy)). Chcę sprawdzić, czy funkcja, którą wygenerowałem, robi to, co powinna, kiedy przekazuję ją innym funkcjom.
D Adams
Dlaczego twoja funkcja nie zwraca czegoś jednorodnego? Taki jest tutaj zapach; możesz szybko i swobodnie pisać kaczkę, ale powinieneś być konsekwentny w tym, co zwracasz.
Makoto
Wydaje mi się, że zawsze mógłbym zwrócić sympy wyrażenie, które czasami zwraca liczbę, a czasami zawiera zmienne.
D Adams
To jest to, co myślę, że chcesz tutaj zrobić; zamiast zwracać wiele różnych typów, zwróć jeden typ i jeśli zajdzie taka potrzeba, zredukuj go do liczby.
Makoto

Odpowiedzi:

191

isinstance()pobiera krotkę klas jako drugi argument. Zwróci wartość true, jeśli pierwszy argument jest instancją dowolnego typu w tej sekwencji:

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

Innymi słowy, isinstance() już oferuje tej funkcji, po wyjęciu z pudełka.

Z isinstance()dokumentacji :

Jeśli classinfo nie jest ani obiektem klasy, ani obiektem typu, może to być krotka obiektów klas lub typów albo może rekurencyjnie zawierać inne takie krotki (inne typy sekwencji nie są akceptowane).

Podkreśl moje; zwróć uwagę na rekurencyjną naturę; (classinfo1, (classinfo2, classinfo3))jest również prawidłową opcją.

Martijn Pieters
źródło
Pomocne, dziękuję!
Yaakov Bressler
11

Tytuł pytania był już dość bliski. Możesz użyć anyi listę:

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

Ale patrząc w dokumentach isinstanceujawnia:

Zwraca wartość true, jeśli argument obiektu jest instancją argumentu classinfo lub jego (bezpośredniej, pośredniej lub wirtualnej) podklasy. Jeśli obiekt nie jest obiektem danego typu, funkcja zawsze zwraca false. Jeśli classinfo nie jest klasą (obiektem typu), może być krotką obiektów typu lub może rekurencyjnie zawierać inne takie krotki (inne typy sekwencji nie są akceptowane). Jeśli classinfo nie jest typem lub krotką typów i takimi krotkami, zgłaszany jest wyjątek TypeError.

Oznacza to, że najlepszym sposobem na to jest

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))
Martin Thoma
źródło
2
Powtarzanie isinstancetylko classinfozmiany nie wydaje mi się zbyt Pythonowe.
Makoto
1
Spróbuj var.__class__. Czy tego chcesz? @Makoto: Zgadzam się. Wcale nie Pythonic!
flamenco
@Makoto Yup. Ale to było coś, co D Adams prawdopodobnie mógł łatwo znaleźć, przeszukując dokumentację pod kątem „dowolnego”. Rozszerzyłem moją odpowiedź na lepszą wersję ... ale oczywiście Martijn Pieters był szybszy ... po raz kolejny.
Martin Thoma
3
any()lista jest ... bezcelowa. Użyj wyrażenia generatora, jeśli musisz go użyć any(), a przynajmniej uzyskasz korzyść z wczesnego wyjścia.
Martijn Pieters
Myślę, że isinstancez krotką jest do zrobienia. Chciałem tylko wspomnieć o rozwiązaniu, anyponieważ wydawało się, że jest to, o co prosi w tytule.
Martin Thoma
4

To rozwiąże Twój problem:

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

Bazując na dokumentacji, istnieje wiele sposobów przekazywania wartości typów do isinstance.

Możesz również spojrzeć na zmysłowy, jeśli próbujesz wykonać bardziej skomplikowaną weryfikację, której to tylko część.

Nathaniel Ford
źródło
isinstance () już oferuje tę funkcjonalność, jako drugi argument przekazuje krotkę ze wszystkimi wymaganymi typami do sprawdzenia
RFV
@ RFV5s Tak .... tak pokazuje przykład, który tutaj podałem. Jaki jest twój sprzeciw?
Nathaniel Ford
1

Generalnie nie powinieneś używać isinstance, ale to, co chcesz zrobić, można osiągnąć za pomocą wbudowanej funkcji any () .

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])
Chad S.
źródło
7
To przesada; isinstance()oferuje funkcjonalność po wyjęciu z pudełka bez użycia any().
Martijn Pieters
@MartijnPieters Nie zdawałem sobie sprawy, że instancja może mieć wiele typów, ale wydaje mi się, że odpowiedź jest nadal dobra, ponieważ pytanie można przyjąć szerzej: „Jak sprawdzić, czy którakolwiek z wartości zwracanych przez określoną funkcję z różnymi parametrami jest prawdą ”
Chad S.
To, czy powinieneś używać, czy nie, nie isinstance()ma znaczenia.
RFV
@ChadS. Chciałbym cię zapytać, dlaczego uważasz, że nie powinien używać isinstance()? Dziękuję Ci.
idature
Ponieważ Python unika sprawdzania typów. To dużo dodatkowego kodu (i cykli procesora) przy niewielkich korzyściach. Preferowane jest pisanie kaczych.
Chad S.