Учитывая произвольный объект python, как лучше всего определить, является ли это числом? Здесь is
определяется как acts like a number in certain circumstances
.
Например, скажем, вы пишете векторный класс. Если задан другой вектор, вы хотите найти скалярное произведение. Если дан скаляр, вы хотите масштабировать весь вектор.
Проверка если что - то int
, float
, long
, bool
раздражает и не распространяется на определенные пользователем объекты , которые могут действовать как числа. Но, __mul__
например , проверки недостаточно, потому что описанный мной векторный класс мог бы определять __mul__
, но это было бы не то число, которое мне нужно.
isinstance(value, Number) and type(value) != bool
Вы хотите проверить, не
Если вы используете Python 2.5 или старше, единственный реальный способ - проверить некоторые из этих «определенных обстоятельств» и посмотреть.
В версии 2.6 или выше вы можете использовать
isinstance
with numbers.Number - абстрактный базовый класс (ABC), который существует именно для этой цели (вcollections
модуле существует гораздо больше ABC для различных форм коллекций / контейнеров, опять же, начиная с версии 2.6; и, также только в этих выпусках вы можете легко добавить свои собственные абстрактные базовые классы, если вам нужно).Баха до 2.5 и ранее, «можно добавить
0
и не повторять» может быть хорошим определением в некоторых случаях. Но вам действительно нужно спросить себя, что именно вы спрашиваете, что то, что вы хотите считать «числом», обязательно должно уметь делать , а что оно должно быть абсолютно неспособным - и проверьте.Это также может потребоваться в версии 2.6 или более поздней, возможно, с целью создания ваших собственных регистраций для добавления типов, которые вам небезразличны, которые еще не были зарегистрированы
numbers.Numbers
- если вы хотите исключить некоторые типы, которые утверждают, что они числа, но вы просто не могу справиться, это требует еще большей осторожности, так как у ABC нетunregister
метода [[например, вы можете создать свой собственный ABCWeirdNum
и зарегистрировать там все такие странные для вас типы, затем сначала проверьтеisinstance
их, чтобы выручить, прежде чем продолжить для проверкиisinstance
нормальногоnumbers.Number
продолжения успешного продолжения.Кстати, если и когда вам нужно проверить,
x
можете или не можете что-то сделать, вам обычно нужно попробовать что-то вроде:Само по себе наличие не
__add__
говорит вам ничего полезного, поскольку, например, все последовательности имеют его для объединения с другими последовательностями. Эта проверка эквивалентна определению, например, «число - это нечто такое, что последовательность таких вещей является допустимым единственным аргументом для встроенной функцииsum
». Совершенно странные типы (например, те, которые вызывают "неправильное" исключение при суммировании до 0, например, например, aZeroDivisionError
илиValueError
& c) будут распространять исключение, но это нормально, пусть пользователь узнает как можно скорее, что такие сумасшедшие типы просто неприемлемы в хорошем Компания;-); но «вектор», суммируемый в скаляр (в стандартной библиотеке Python его нет, но, конечно, они популярны как сторонние расширения), здесь также будет неправильный результат, поэтому (например,вариант «не допускается повторение» (например, проверка, котораяiter(x)
вызывает повышениеTypeError
, или наличие специального метода__iter__
- если вы используете версию 2.5 или более раннюю и, следовательно, нуждаетесь в собственных проверках).Краткого ознакомления с такими сложностями может быть достаточно, чтобы мотивировать вас полагаться вместо этого на абстрактные базовые классы, когда это возможно ... ;-).
источник
Это хороший пример того, как действительно проявляются исключения. Просто делайте то, что вы делаете с числовыми типами, и ловите их
TypeError
от всего остального.Но очевидно, что это только проверяет , является ли операция по работам , не является ли это имеет смысл ! Единственное реальное решение для этого - никогда не смешивать типы и всегда точно знать, к какому классу типов принадлежат ваши значения.
источник
isinstance
действительно может быть полезен во многих случаях (== «проверьте, имеет ли смысл», а также формальную применимость операций). Трудный переход для тех, кто давно занимается только Python, но очень важная тонкая тенденция в философии Python, игнорировать которую было бы серьезной ошибкой.collections.Sequence
и друзей). Но, черт возьми, таких классов для чисел, векторов или любых других математических объектов не существует.Умножьте объект на ноль. Любое число, умноженное на ноль, равно нулю. Любой другой результат означает, что объект не является числом (включая исключения)
Таким образом, использование isNumber даст следующий результат:
Вывод:
Вероятно, в мире есть нечисловые объекты, которые
__mul__
возвращают ноль при умножении на ноль, но это крайнее исключение. Это решение должно охватывать весь нормальный и разумный код, который вы создаете / используете.Пример numpy.array:
вывод:
источник
True * 0 == 0
int
поэтому моя функция будет правильно говорить, что логические значения - это числа.Перефразируя свой вопрос, вы пытаетесь определить, является ли что-то коллекцией или отдельным значением. Попытка сравнить, является ли что-то вектором или числом, сравнивает яблоки с апельсинами - у меня может быть вектор строк или чисел, и у меня может быть одна строка или одно число. Вас интересует, сколько у вас их (1 или больше) , а не какой у вас тип на самом деле.
Мое решение этой проблемы - проверить, является ли ввод одним значением или коллекцией, проверив наличие
__len__
. Например:Или, для подхода с утиной типизацией, вы можете попробовать
foo
сначала выполнить итерацию :В конце концов, легче проверить, является ли что-то векторным, чем проверять, является ли что-то скалярным. Если у вас есть значения разного типа (например, строковые, числовые и т. Д.), То логика вашей программы может нуждаться в некоторой доработке - как вы вообще пытались умножить строку на числовой вектор?
источник
Чтобы обобщить / оценить существующие методы:
(Я пришел сюда по этому вопросу )
Код
источник
float('nan'), 'nan', '123.45', '42', '42a', '0x8', '0xa'
добавлюmath.isnan
Наверное, лучше сделать наоборот: проверить, вектор ли это. Если это так, вы производите скалярное произведение, а во всех остальных случаях пытаетесь скалярное умножение.
Проверить вектор легко, так как он должен принадлежать к типу вашего векторного класса (или быть унаследованным от него). Вы также можете просто попробовать сначала выполнить скалярное произведение, а если это не поможет (= на самом деле это не вектор), затем вернуться к скалярному умножению.
источник
Просто чтобы добавить. Возможно, мы можем использовать комбинацию isinstance и isdigit следующим образом, чтобы определить, является ли значение числом (int, float и т. Д.)
если isinstance (num1, int) или isinstance (num1, float) или num1.isdigit ():
источник
Для класса гипотетических векторов:
Предположим
v
, это вектор, и мы умножаем его наx
. Если есть смысл умножать каждый компонентv
наx
, мы, вероятно, имели в виду именно это, поэтому сначала попробуйте это. Если нет, может, мы расставим точки? В противном случае это ошибка типа.РЕДАКТИРОВАТЬ - приведенный ниже код не работает, потому что
2*[0]==[0,0]
вместо повышенияTypeError
. Я оставляю это, потому что это было прокомментировано.источник
x
- вектор, тогда[comp * x for comp in self]
будетx
получен внешний продуктv
. Это тензор 2-го ранга, а не скаляр.comp*x
будет масштабироватьсяx
путемcomp
, я предполагал , что это поднимет TypeError. К сожалению, на самом деле он будет сцеплятьсяx
со своимcomp
временем. К сожалению.x
это вектор, то у него должен быть__rmul__
метод (__rmul__ = __mul__
), чтобы онcomp * x
масштабировался такx
же,x * comp
как и предполагалось.У меня была аналогичная проблема при реализации своего рода векторного класса. Один из способов проверить число - просто преобразовать его в единицу, т. Е. Используя
Это должно исключать случаи, когда x не может быть преобразовано в число; но может также отклонять другие типы числовых структур, которые могут быть действительными, например комплексные числа.
источник
Если вы хотите вызывать разные методы в зависимости от типа (ов) аргумента, посмотрите
multipledispatch
.К сожалению (насколько мне известно) мы не можем писать,
@dispatch(Vector)
поскольку мы все еще определяем типVector
, поэтому имя типа еще не определено. Вместо этого я использую базовый типlist
, который позволяет вам даже найти точечное произведение aVector
и alist
.источник
Короткий и простой способ:
Вывод :
Если объект является строкой, будет возвращено 'False':
Вывод :
источник
У вас есть элемент данных, скажем,
rec_day
что при записи в файл будетfloat
. Но во время обработки программы это может быть либоfloat
,int
либоstr
тип (str
используется при инициализации новой записи и содержит фиктивное значение флага).Затем вы можете проверить, есть ли у вас номер с этим
Я структурировал программу на Python таким образом и просто вставил «патч обслуживания», используя это как числовую проверку. Это питонический путь? Скорее всего, нет, потому что раньше я программировал на КОБОЛЕ.
источник
Вы можете использовать функцию isdigit ().
источник