Как уже отвечали другие, могут быть и другие числовые типы, кроме тех, которые вы упомянули.
Один из подходов заключается в явной проверке нужных вам возможностей, например,
# Python 2
def is_numeric(obj):
attrs = ['__add__', '__sub__', '__mul__', '__div__', '__pow__']
return all(hasattr(obj, attr) for attr in attrs)
# Python 3
def is_numeric(obj):
attrs = ['__add__', '__sub__', '__mul__', '__truediv__', '__pow__']
return all(hasattr(obj, attr) for attr in attrs)
Это работает для всех ваших примеров, кроме последнего, numpy.array(['1'])
. Это потому, что numpy.ndarray
имеет специальные методы для числовых операций, но вызывает TypeError, если вы пытаетесь использовать их ненадлежащим образом для строковых или объектных массивов. Вы можете добавить явную проверку для этого как
... and not (isinstance(obj, ndarray) and obj.dtype.kind in 'OSU')
Это может быть достаточно хорошо.
Но ... вы никогда не сможете быть 100% уверенными в том, что кто-то не определит другой тип с таким же поведением, поэтому более надежный способ - на самом деле попытаться выполнить вычисление и поймать исключение что-то вроде
def is_numeric_paranoid(obj):
try:
obj+obj, obj-obj, obj*obj, obj**obj, obj/obj
except ZeroDivisionError:
return True
except Exception:
return False
else:
return True
но в зависимости от того, как часто вы планируете звонить, используйте его и с какими аргументами, это может быть непрактично (может быть медленным, например, с большими массивами).