Applications of '~' (tilde) operator in Python

Question:

I just discovered the bitwise complement unary operation in Python via this question and have been trying to come up with an actual application for it, and if not, to determine if it’s generally safe to overload the operator (by overriding the __invert__ method) for other uses. The example given in the question fails with a TypeError, and the link provided seems pretty intimidating. Here’s some fiddling around to see ~ in use:

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)

Are there any examples of valid use-cases for this operator that I should be aware of? And even if there are, is it generally acceptable to override this operator for types other than int?

Asked By: Alec

||

Answers:

Are there any examples of valid use-cases for this operator that I should be aware of? And even if there are, is it generally acceptable to override this operator for types other than int?

Typically, you would not want to overload the ~ operator just because it is fun. It makes reading difficult. But sometimes, such overload for types other than int makes sense. Take a look at how SQLAlchemy puts it to good use.

Answered By: UltraInstinct

The standard use cases for the bitwise NOT operator are bitwise operations, just like the bitwise AND &, the bitwise OR |, the bitwise XOR ^, and bitwise shifting << and >>. Although they are rarely used in higher level applications, there are still some times where you need to do bitwise manipulations, so that’s why they are there.

Of course, you may overwrite these for custom types, and in general you are not required to follow any specific semantics when doing so. Just choose what makes sense for your type and what still fits the operator in some way.

If the operation is obscure and better explained with a word or two, then you should use a standard method instead. But there are some situations, especially when working with number related types, that could have some mathematical-like operations which fit the bitwise operators, and as such are fine to use those.

Just like you would overwrite standard operators like + and - only for meaningful operations, you should try to do the same for bitwise operators.


The reason ~~True, ~~False gives you (1, 0) is because the bool type does not define its own __invert__ operation. However, int does; and bool is actually a subtype of int. So bool actually inherits the logic of all bitwise and arithmetical operators. That’s why True + True == 2 etc.

Answered By: poke

You can use that operator in conjunction with the negation operator (-) to increment a number by 1. For example:

x = 5
assert -~x == 6

This is the only practical way I’ve ever used the ~ operator. Any other way it is used for anything apart from numbers, is generally context dependent and often add a level of complexity to understanding code.
For languages such as C++, Swift, Ruby, etc, you can overload this operator to mean anything which sometimes makes the code harder to digest quickly

Answered By: smac89

It’s commonly used in code golf as a shortcut for a few things, such as using ~x rather than -x-1 or ~my_bool rather than not my_bool.

Answered By: user6412179

As others have mentioned, it can be really neat when traversing lists.

for i in range(n):
    mylist[~i]
    #much prettier than mylist[-i-1]

Take a look at an example which rotates a matrix clockwise by 90 degrees:

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]

(This snippet was taken from here)

Answered By: A73rnA

Some methods such as the String find() will return -1 indicating ‘not found’. This is because character index 0 is a valid sub-string start position. Because integers are stored as two’s compliment the ~ operator can then neatly be used to discriminate between -1 and everything else.

For example:

test_sentence_1 = "There is a tilde in here"
test_sentence_2 = "There is not one in here"

if ~test_sentence_1.find('tilde'):
    print("1. Tilde Found")
else:
    print("1. Tilde NOT Found")

if ~test_sentence_2.find('tilde'):
    print("2. Tilde Found")
else:
    print("2. Tilde NOT Found")

1. Tilde Found
2. Tilde NOT Found
>>>

This works because signed integers are stored as two’s compliment and if
you bit flip -1, which is what ‘~’ does, then you get 0 ie False.
If you bit flip anything else but -1 you get a non-zero ie True

This use of tilde was common in C where many functions would return -1 to indicate failure

Answered By: James

~x is equivalent to (-x) – 1.

So it is handy to traverse an array or list in case we want to simultaneously operate on elements from both sides:

ie:

  • (s[0] and s[len(s) – 1])

  • (s[1] and s[len(s) – 2])

  • def tilde(self, nums: List[int]) -> int:
      for i in range(len(nums)):
        print(nums[i], nums[~i])
    

For an input [1,2,3,4,5,6,7,8,9]
Output is :

1 9
2 8
3 7
4 6
5 5
6 4
7 3
8 2
9 1
Answered By: Joe