Как правильно использовать python isinstance(), чтобы проверить, является ли переменная числом?
Я нашел старый код Python, который делал что-то вроде:
if type(var) is type(1):
...
Как и ожидалось, pep8
жалуется на это, рекомендуя использовать isinstance()
.
Теперь проблема в том, что модуль numbers
был добавлен в Python 2.6, и мне нужно написать код, который работает с Python 2.5 +
Итак, if isinstance(var, Numbers.number)
не является решением.
Что было бы правильным решением в этом случае?
Ответы
Ответ 1
Вы можете использовать types
модуль:
>>> import types
>>> var = 1
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
>>> isinstance(var, NumberTypes)
True
Обратите внимание на использование кортежа для тестирования нескольких типов.
Под капотом IntType
является просто псевдонимом для int
и т.д.:
>>> isinstance(var, (int, long, float, complex))
True
Тип complex
требует, чтобы ваш python был скомпилирован с поддержкой сложных чисел; если вы хотите защитить это, используйте блок try/except:
>>> 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)
...
или если вы просто используете типы напрямую:
>>> try:
... NumberTypes = (int, long, float, complex)
... except NameError:
... # No support for complex numbers compiled
... NumberTypes = (int, long, float)
...
Наконец, вы можете использовать numbers.Numbers
абстрактный базовый тип (новый в Python 2.6), чтобы также поддерживать пользовательские числовые типы, которые не выводятся непосредственно из вышеперечисленных типов:
>>> import numbers
>>> isinstance(var, numbers.Number)
True
Этот модуль делает предположение, что тип complex
включен; вы получите ошибку импорта, если это не так.
Ответ 2
Python 2 поддерживает четыре типа для чисел int
, float
, long
и complex
и python 3.x
поддерживает 3: int
, float
и 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
Ответ 3
В зависимости от того, что вы используете в duck typing, может быть лучший подход (конечно обычно рекомендуется). Проблема с подхода Martijn Pieters заключается в том, что вы всегда будете пропускать некоторые типы номеров из своего списка. С моей головы ваш код не будет работать: sympy рациональные числа, произвольные целые числа точности и любая реализация сложных чисел.
Один из вариантов - написать такую функцию:
def is_number(thing):
try:
thing + 1
return True
except TypeError:
return False
Этот код должен работать с любой разумной реализацией числа. Конечно, есть существенный недостаток: он также будет работать с необоснованной реализацией множества не чисел (т.е. Если оператор плюс перегружен и принимает целое число).
Другая альтернатива (в зависимости от того, почему вам нужно знать, является ли что-то числом), - это просто предположить, что это число, и если это не ошибки, будет выдаваться какой бы бит кода не требовал числа.
Я не говорю, что эти подходы всегда лучше (в отличие от некоторых людей...), что они заслуживают внимания.