'〜'的应用Python中的(波浪号)运算符

时间:2016-07-08 16:54:51

标签: python python-3.x operator-overloading bit-manipulation tilde

我刚刚通过bitwise complement unary operation在Python中发现了this question,并且一直试图为它提出一个实际的应用程序,如果没有,确定它是否通常可以安全地过载运算符(通过覆盖__invert__方法)用于其他用途。问题中给出的示例失败了TypeError,提供的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以外的类型覆盖此运算符吗?

6 个答案:

答案 0 :(得分:13)

按位NOT运算符的标准用例是按位运算,就像按位AND &,按位OR |,按位XOR ^和按位移位{{ 1}}和<<。尽管它们很少用于更高级别的应用程序,但有时候您仍需要进行按位操作,这就是它们存在的原因。

当然,您可以为自定义类型覆盖这些,并且通常在执行此操作时不需要遵循任何特定语义。只需选择对您的类型有意义的内容以及以某种方式仍然适合运营商的内容。

如果操作模糊不清,用一两句话更好地解释,那么你应该使用标准方法。但是在某些情况下,特别是在处理与数字相关的类型时,可能会有一些类似于数学的运算,这些运算符合位运算符,因此可以使用它们。

就像你会覆盖>>+之类的标准运算符只是为了进行有意义的操作一样,你应该尝试对按位运算符执行相同的操作。

-为您提供~~True, ~~False的原因是因为(1, 0)类型未定义自己的bool操作。但是,__invert__会这样做; int实际上是bool的子类型。所以int实际上继承了所有按位和算术运算符的逻辑。这就是为什么bool等等。

答案 1 :(得分:6)

  

我应该注意这个运营商的有效用例的例子吗?即使有,对于int以外的类型覆盖此运算符通常是可以接受的吗?

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

答案 2 :(得分:2)

您可以将该运算符与否定运算符(-)结合使用,将数字增加1.例如:

x = 5
assert -~x == 6

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

答案 3 :(得分:2)

code golf中常用它作为一些内容的快捷方式,例如使用~x而不是-x-1~my_bool而不是not my_bool。< / p>

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

某些方法,例如 String find() 将返回 -1 表示“未找到”。这是因为字符索引 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
>>>

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

这种波浪号的使用在 C 中很常见,其中许多函数会返回 -1 以指示失败