Приложения оператора ~ ~ (тильда) в Python
Я только что обнаружил поразрядное дополнение унарной операции в Python через этот вопрос и пытался с фактическим приложением для него, а если нет, определить, безопасно ли вообще перегружать оператора (путем переопределения метода __invert__
) для других целей. Пример, приведенный в вопросе, терпит неудачу с TypeError
, а ссылка кажется довольно запугивающей. Здесь некоторые возились, чтобы увидеть ~
в использовании:
from bitstring import BitArray
x = 7
print(~x)
# -8
print(BitArray(int=x, length=4).bin)
# '0111'
print(BitArray(int=~x, length=4).bin)
# '1000'
print(~~True, ~~False)
# 1 0
for i in range(-100, 100):
assert i + ~i == -1
assert i ^ ~i == -1
assert bool(i) == ~~bool(i)
Есть ли примеры действительных случаев использования этого оператора, о которых я должен знать? И даже если есть, вообще ли приемлемо переопределять этот оператор для типов, отличных от int
?
Ответы
Ответ 1
Стандартными вариантами использования для побитового оператора NOT являются побитовые операции, такие как побитовый И &
, побитовый OR |
, побитовый XOR ^
и побитовый сдвиг <<
и >>
. Хотя они редко используются в приложениях более высокого уровня, есть еще несколько раз, когда вам нужно выполнять побитовые манипуляции, поэтому поэтому они есть.
Конечно, вы можете перезаписать их для пользовательских типов, и в целом вы не обязаны следовать какой-либо конкретной семантике при этом. Просто выберите то, что имеет смысл для вашего типа и что по-прежнему подходит для оператора.
Если операция неясна и лучше объясняется словом или двумя, тогда вместо этого вы должны использовать стандартный метод. Но есть некоторые ситуации, особенно при работе с числовыми типами, которые могут иметь некоторые математические операции, которые соответствуют побитовым операторам и, как таковые, могут их использовать.
Как и для стандартных операторов, таких как +
и -
, только для значимых операций, вы должны попытаться сделать то же самое для побитовых операторов.
Причина ~~True, ~~False
дает вам (1, 0)
, потому что тип bool
не определяет свою собственную операцию __invert__
. Однако int
делает; и bool
на самом деле является подтипом int
. Таким образом, bool
фактически наследует логику всех поразрядных и арифметических операторов. Вот почему True + True == 2
и т.д.
Ответ 2
Есть ли примеры действительных случаев использования этого оператора, о которых я должен знать? И даже если есть, допустимо ли вообще переопределять этот оператор для типов, отличных от int?
Как правило, вы не хотите перегружать оператор ~
только потому, что это весело. Это затрудняет чтение. Но иногда такая перегрузка для типов, отличных от int
, имеет смысл. Посмотрите, как SQLAlchemy хорошо использует его.
Ответ 3
Вы можете использовать этот оператор в сочетании с оператором отрицания (-
), чтобы увеличить число на 1. Например:
x = 5
assert -~x == 6
Это единственный практический способ, которым я когда-либо использовал оператор ~
. Любой другой способ, который он использует для чего угодно, кроме чисел, обычно зависит от контекста и часто добавляет уровень сложности в понимание кода.
Для таких языков, как С++, Swift, Ruby и т.д., Вы можете перегрузить этот оператор, чтобы означать что-нибудь, что иногда затрудняет сложный анализ кода.
Ответ 4
Он обычно используется в code golf как ярлык для нескольких вещей, например, ~x
вместо -x-1
или ~my_bool
, а не not my_bool
.
Ответ 5
Как уже упоминалось, он может быть очень аккуратным при просмотре списков.
for i in range(n):
mylist[~i]
#much prettier than mylist[-i-1]
Взгляните на пример, который вращает матрицу по часовой стрелке на 90 градусов:
def rotate( A):
n = len(A)
for i in range(n/2):
for j in range(n-n/2):
A[i][j], A[~j][i], A[~i][~j], A[j][~i] = \\
A[~j][i], A[~i][~j], A[j][~i], A[i][j]
(Этот фрагмент был взят из здесь)