Python tilde унарный оператор как отрицательный numpy bool array
Должен быть простой вопрос, но я не могу найти ответ нигде. Оператор ~
в python документируется как побитовый оператор инверсии. Хорошо. Я заметил, по-видимому, шизофреническое поведение, хотя и остроумие:
~True -> -2
~1 -> -2
~False -> -1
~0 -> -1
~numpy.array([True,False],dtype=int) -> array([-2,-1])
~numpy.array([True,False],dtype=bool) -> array([False,True])
В первых 4 примерах я вижу, что python реализует (как документировано) ~x = -(x+1)
, причем вход обрабатывается как int, даже если он булеван. Следовательно, для скалярного булева ~
не рассматривается как логическое отрицание. Не то, чтобы поведение было одинаковым в массиве numpy, определенном с булевыми значениями, с помощью типа int.
Почему ~
затем работает как логический оператор отрицания в булевом массиве (также обратите внимание: ~numpy.isfinite(numpy.inf) -> True
?)?
Очень обидно, что я должен использовать not()
на скаляре, но not()
не будет работать, чтобы свести на нет массив. Тогда для массива я должен использовать ~
, но ~
не будет работать, чтобы свести на нет скаляр...
Ответы
Ответ 1
not
реализуется с помощью специального метода __nonzero__
, который требуется для возврата либо True
, либо False
, поэтому он не может дать требуемый результат. Вместо этого используется оператор ~
, который реализуется специальным методом __not__
. По той же причине вместо and
и or
используются &
и |
.
PEP 335, направленный на то, чтобы разрешить перегрузку логических операторов, но был отклонен из-за чрезмерных издержек (это, например, усложняло инструкции if
). PEP 225 предлагает общий синтаксис для "элементарных" операторов, который обеспечил бы более общее решение, но был отложен. Похоже, что нынешняя ситуация, хотя и неудобная, не является достаточно болезненной, чтобы заставить меняться.
np.isfinite
при вызове скаляра возвращает значение типа np.bool_
, а не bool
. np.bool_
- это также тип, который вы получаете при извлечении скалярного значения из массива bool dtype. Если вы используете np.True_
и np.False_
вместо True
и False
, вы получите согласованное поведение в ~
.