2012-06-26 8 views
32

Znalazłem jakiś stary kod Pythona, który robił coś takiego:Jak poprawnie używać funkcji isInstance() w Pythonie, aby sprawdzić, czy zmienna jest liczbą?

if type(var) is type(1): 
    ... 

Zgodnie z oczekiwaniami, pep8 narzeka tego zalecając wykorzystanie isinstance().

Teraz problemem jest to, że moduł numbers został dodany w Pythonie 2.6 i muszę napisać kod, który działa z Python 2.5+

Więc if isinstance(var, Numbers.number) nie jest rozwiązaniem.

Jakie byłoby właściwe rozwiązanie w tym przypadku?

+0

Jeśli chcesz używać numpy, 'numpy.isfinite' powinno wystarczyć. –

Odpowiedz

83

można użyć types module:

>>> import types 
>>> var = 1 
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType) 
>>> isinstance(var, NumberTypes) 
True 

Zanotować użycie krotki do testowania przeciwko wielu typom.

Pod maską IntType tylko aliasem int itp .:

>>> isinstance(var, (int, long, float, complex)) 
True 

Typ complex wymaga, aby pyton został skompilowany ze wsparciem dla liczb zespolonych; jeśli chcesz ustrzec dla tego zastosowania spróbuj/z wyjątkiem bloku:

>>> try: 
...  NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType) 
... except AttributeError: 
...  # No support for complex numbers compiled 
...  NumberTypes = (types.IntType, types.LongType, types.FloatType) 
... 

lub jeśli po prostu używać typów bezpośrednio:

>>> try: 
...  NumberTypes = (int, long, float, complex) 
... except NameError: 
...  # No support for complex numbers compiled 
...  NumberTypes = (int, long, float) 
... 

Last but not least, można użyć numbers.Numbers abstract base type (nowość Python 2.6) również obsługują niestandardowe typy numeryczne, które nie wynikają bezpośrednio z powyższych typów:

>>> import numbers 
>>> isinstance(var, numbers.Number) 
True 

moduł ten czyni założenie, że typ complex jest włączona; otrzymasz błąd importu, jeśli tak nie jest.

+3

'isinstance()' może wziąć krotek obiektów?!? Woah, stary ... –

+0

@Def_Os: tak, i to jest funkcja od czasu Python 2.2. –

+0

Naprawdę powinieneś umieścić to na górze swojej odpowiedzi. –

13

Python 2 obsługuje cztery typy dla numerów int, float, long i complex i python 3.x obsługuje 3: int, float i complex

>>> num = 10 
>>> if isinstance(num, (int, float, long, complex)): #use tuple if checking against multiple types 
     print('yes it is a number') 

yes it is a number 
>>> isinstance(num, float) 
False 
>>> isinstance(num, int) 
True 
>>> a = complex(1, 2) 
>>> isinstance(a, complex) 
True 
2

W zależności od tego, co używasz tego w duck typing mogłyby być lepsze podejście (to certainlycommonlyrecommended). Problem z podejściem Martijna Pietersa polega na tym, że zawsze będziesz pomijać niektóre rodzaje numerów z twojej listy. Poza zakresem mojej głowy twój kod nie będzie działał z: sympatyczne liczby wymierne, arbitralne liczby całkowite i dowolna implementacja liczb zespolonych.

Jedną z alternatyw jest napisać funkcję tak:

def is_number(thing): 
    try: 
     thing + 1 
     return True 
    except TypeError: 
     return False 

Ten kod powinien działać z każdym rozsądnym realizacji szeregu. Oczywiście istnieje poważna wada: będzie również działać z nieuzasadnioną implementacją dużej ilości liczb (to znaczy, jeśli operator plus jest przeciążony i akceptuje liczbę całkowitą).

Inną alternatywą (w zależności od tego, dlaczego musisz wiedzieć, że coś jest liczbą) jest po prostu założenie, że jest to liczba, a jeśli nie, to błędy zostaną wygenerowane przez dowolny fragment kodu, który wymaga numeru.

Nie twierdzę, że te podejścia są zawsze lepsze (w przeciwieństwie do niektórych osób ...) tylko dlatego, że warto je rozważyć.

Powiązane problemy