“~”(代字号)运算符在 Python 中的应用

Applications of '~' (tilde) operator in Python

我刚刚发现所提供的 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 看起来很吓人。这里有一些摆弄来查看 ~ 的使用情况:

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 以外的类型覆盖此运算符通常是否可以接受?

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?

通常,您不会因为 ~ 运算符很有趣就重载它。这使阅读变得困难。但有时,这种重载 int 以外的类型是有道理的。 Take a look at how SQLAlchemy puts it to good use.

按位非运算符的标准用例是按位运算,就像按位与 &、按位或 |、按位异或 ^ 和按位移位<<>>。尽管它们很少用于更高级别的应用程序,但有时您仍然需要进行按位操作,因此这就是它们存在的原因。

当然,您可以为自定义类型覆盖这些,并且通常您在这样做时不需要遵循任何特定的语义。只需选择对您的类型有意义的内容以及在某种程度上仍适合操作员的内容。

如果操作晦涩难懂,一两句话就能解释清楚,那么你应该改用标准方法。但是在某些情况下,尤其是在处理与数字相关的类型时,可能会有一些适合按位运算符的类似数学的运算,因此可以很好地使用它们。

就像您仅为有意义的操作覆盖 +- 等标准运算符一样,您应该尝试对按位运算符执行相同的操作。


~~True, ~~False 给你 (1, 0) 的原因是因为 bool 类型没有定义它自己的 __invert__ 操作。但是,int 可以; bool 实际上是 int 的子类型。所以bool实际上继承了所有位运算符和算术运算符的逻辑。这就是为什么 True + True == 2 等等

您可以将该运算符与取反运算符 (-) 结合使用,使数字递增 1。例如:

x = 5
assert -~x == 6

这是我使用过 ~ 运算符的唯一实用方法。它用于除数字之外的任何其他方式通常取决于上下文,并且通常会增加一定程度的复杂性以理解代码。 对于 C++、Swift、Ruby 等语言,您可以重载此运算符以表示有时会使代码难以快速理解的任何内容

它通常在 code golf 中用作某些事情的快捷方式,例如使用 ~x 而不是 -x-1~my_bool 而不是 not my_bool .

正如其他人所提到的,遍历列表时它可以非常整洁。

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]

(此片段摘自 here

某些方法,例如 String find() 将 return -1 表示 'not found'。这是因为字符索引 0 是有效的子字符串起始位置。因为整数存储为补码,所以 ~ 运算符可以巧妙地用于区分 -1 和其他所有内容。

例如:

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
>>>

这是有效的,因为有符号整数存储为二进制补码,如果 你位 flip -1,这就是'~'所做的,然后你得到 0 即 False。 如果你翻转除 -1 之外的任何其他内容,你会得到一个非零值,即 True

波浪号的这种用法在 C 中很常见,其中许多函数 return -1 表示失败