Python中的波浪符运算符

q7solyqu  于 2023-01-08  发布在  Python
关注(0)|答案(9)|浏览(252)

在Python中波浪符的用法是什么?
我可以考虑的一件事是在字符串或列表的两端做一些事情,比如检查字符串是否是回文的:

def is_palindromic(s):
    return all(s[i] == s[~i] for i in range(len(s) / 2))

还有其他好的用法吗?

q0qdq0h2

q0qdq0h21#

它是一个一元运算符(只带一个参数),是从C语言中借来的,C语言中所有的数据类型只是解释字节的不同方式,它是“反相”或“求补”运算,输入数据的所有位都被反转。
在Python中,对于整数,整数twos-complement representation的位被反转(就像b <- b XOR 1中的每一位),结果再次被解释为二进制补码整数,所以对于整数,~x等价于(-x) - 1
~运算符的具体形式是operator.invert。要在您自己的类中支持此运算符,请为其给予一个__invert__(self)方法。

>>> import operator
>>> class Foo:
...   def __invert__(self):
...     print 'invert'
...
>>> x = Foo()
>>> operator.invert(x)
invert
>>> ~x
invert

任何类,如果在其中具有示例的“补码”或“逆运算符”是有意义的,而该示例又是同一个类的示例,则该类都可能是inverse运算符的候选对象。但是,运算符重载如果被误用,可能会导致混淆,因此,在为类提供__invert__方法之前,请确保这样做确实有意义。(注意,字节串[例如:'\xff' ]不支持此运算符,即使反转字节字符串的所有位有意义。)

2lpgd968

2lpgd9682#

~是python中的按位补码运算符,它主要计算-x - 1
所以一张table看起来像

i  ~i
-----
0  -1
1  -2
2  -3
3  -4 
4  -5 
5  -6

因此,对于i = 0,它将比较s[0]s[len(s) - 1],对于i = 1,它将比较s[1]s[len(s) - 2]
至于您的另一个问题,这对bitwise hacks范围可能有用。

bgtovc5b

bgtovc5b3#

除了作为一个按位求补运算符,~还可以帮助还原一个 boolean 值,尽管它不是传统的bool类型,而应该使用numpy.bool_
对此进行了解释,

import numpy as np
assert ~np.True_ == np.False_

反转逻辑值有时会很有用,例如,下面的~运算符用于清理数据集并返回一个不含NaN的列。

from numpy import NaN
import pandas as pd

matrix = pd.DataFrame([1,2,3,4,NaN], columns=['Number'], dtype='float64')
# Remove NaN in column 'Number'
matrix['Number'][~matrix['Number'].isnull()]
gijlo24d

gijlo24d4#

需要注意的是,在数组索引的情况下,array[~i]等于reversed_array[i],可以看作是从数组末尾开始索引:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
    ^                 ^
    i                ~i
flvlnr44

flvlnr445#

我在实践中唯一一次使用这个方法是在numpy/pandas中,例如,在.isin()dataframe method中。
在文档中,他们展示了这个基本示例

>>> df.isin([0, 2])
        num_legs  num_wings
falcon      True       True
dog        False       True

但是,如果您希望所有的行都不在[0,2]中,该怎么办?

>>> ~df.isin([0, 2])
        num_legs  num_wings
falcon     False       False
dog        True        False
t9eec4r0

t9eec4r06#

我正在解决这个leetcode problem,一个名为Zitao Wang的用户遇到了这个beautiful solution
问题是这样的,对于给定数组中的每个元素,在O(n)时间内求出所有剩余数字的乘积,而不使用除数和
标准品溶液为:

Pass 1: For all elements compute product of all the elements to the left of it
Pass 2: For all elements compute product of all the elements to the right of it
        and then multiplying them for the final answer

他的解决方案只使用了一个for循环,使用~动态计算左积和右积

def productExceptSelf(self, nums):
    res = [1]*len(nums)
    lprod = 1
    rprod = 1
    for i in range(len(nums)):
        res[i] *= lprod
        lprod *= nums[i]
        res[~i] *= rprod
        rprod *= nums[~i]
    return res
wfsdck30

wfsdck307#

解释为什么-x -1通常是正确的(对于整数)

有时候(example)时,人们会对~运算符的数学行为感到惊讶,例如,他们可能会推断,~18的结果应该是13,而不是-19(由于bin(18)给出'0b10010',反转这些位将给予“0 b 01101”,它表示13-对吗?)或者他们可能期望237(将输入视为带符号的8位量),或对应于较大整数大小(例如机器字长)的某一其它正值。
注意,这里,位11101101signed解释是... 237(将其视为无符号,给予237)。对于更大的位数,也会发生同样的情况。事实上,只要我们使用至少6位,并将结果视为有符号,我们就会得到相同的答案:-19.
数学规则--先求反再减1--对所有输入都有效,只要我们使用足够的位,并将结果视为有符号。
而且,这是Python,概念上数字使用任意数量的位。实现将根据表示数字所需的内容自动分配更多的空间。(例如,如果值“适合”一个机器字,那么只使用一个;数据类型抽象了将数字符号扩展到无穷大的过程。)它也没有任何单独的无符号整数类型;在Python中,整数是带符号的(毕竟,既然我们无法控制所使用的内存量,那么拒绝访问负值又有什么意义呢?)
这打破了许多来自C环境的人的直觉,在C环境中,只使用无符号类型进行位操作,然后在以后应用2s补码解释(并且只有在适当的时候;如果一个值被当作一组“标志”,那么带符号的解释就不太可能有意义)。然而,Python对~的实现与其他设计选择是一致的。

如何强制无符号行为

如果我们想从反转18的位得到13237或类似的任何东西,我们将需要一些外部机制来指定反转多少位。(同样,18在概念上在其二进制表示中具有 * 任意多个 * 前导0,以任意位数表示;将它们反转将导致前导1的内容;并且在2S补码中解释它将给予否定结果)。
最简单的方法是屏蔽掉这些任意多的位,为了从反转18得到13,我们需要5位,所以我们用0b11111屏蔽,也就是31。更一般地说(并为原始行为给出相同的接口):

def invert(value, bits=None):
    result = ~value
    return result if bits is None else (result & ((1 << bits) - 1))

根据Andrew Jenkins在相关示例问题中的回答,另一种方法是直接与掩码进行XOR运算。有趣的是,我们可以使用XOR来处理默认的任意精度情况。我们只使用任意大小的掩码,即在概念上具有任意数量1位的二进制表示的整数-即-1。因此:

def invert(value, bits=None):
    return value ^ (-1 if bits is None else ((1 << bits) - 1))

然而,像这样使用XOR对于负value会给予奇怪的结果--因为所有那些在XOR掩码“之前”(在更有效的位置)的任意多个设置位都没有被清除:

>>> invert(-19, 5) # notice the result is equal to 18 - 32
-14
pftdvrlh

pftdvrlh8#

叫做二进制一的补码(~)
它返回一个数的二进制数的补码。它翻转位。二进制数2是00000010。它的补码是11111101。
这是-3的二进制数。所以,结果是-3。类似地,~1的结果是-2。

~-3

输出:2
同样,-3的补码是2。

iyfamqjs

iyfamqjs9#

这是一个次要的用法是波浪号...

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio)) 
    return data.loc[~in_test_set], data.loc[in_test_set]

上面的代码来自"机器学习实践"
可以使用波浪号(~号)作为-号索引标记的替代
就像对整数索引使用minus-is一样
前)

array = [1,2,3,4,5,6]
print(array[-1])

是一回事
第一个月

相关问题