Python的Tilde运营商
Tilde运营商在Python中的用法是什么?
我能想到的一件事是在字符串或列表的两侧做某事,例如检查字符串是否是alnindromic:
def is_palindromic(s):
return all(s[i] == s[~i] for i in range(len(s) / 2))
其他任何好的用法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
它是从C借用的一单位运算符(采用单个参数),其中所有数据类型都是解释字节的不同方法。它是“反转”或“补充”操作,其中所有输入数据的所有位都相反。
在Python中,对于整数,二十os-complement表示 (如
b< - b xor 1
在每个单独的位),结果再次解释为两个组合整数。因此,对于整数,〜x
等效于( - x)-1
。提供
〜
运算符的重新形式为operator.invert
。要在您自己的课程中支持此操作员,请给它一个__ iNvert __(self)
方法。具有同一类实例的实例的“补充”或“倒数”的任何类别都是倒置操作员的候选者。但是,如果滥用滥用,操作员的过载可能会导致混乱,因此请确保在向您的班级提供
invert __
方法之前确实有意义。 (请注意,字节串[ex:'\ xff'
]也不支持此操作员,即使将字节弦的所有位倒置是有意义的。)It is a unary operator (taking a single argument) that is borrowed from C, where all data types are just different ways of interpreting bytes. It is the "invert" or "complement" operation, in which all the bits of the input data are reversed.
In Python, for integers, the bits of the twos-complement representation of the integer are reversed (as in
b <- b XOR 1
for each individual bit), and the result interpreted again as a twos-complement integer. So for integers,~x
is equivalent to(-x) - 1
.The reified form of the
~
operator is provided asoperator.invert
. To support this operator in your own class, give it an__invert__(self)
method.Any class in which it is meaningful to have a "complement" or "inverse" of an instance that is also an instance of the same class is a possible candidate for the invert operator. However, operator overloading can lead to confusion if misused, so be sure that it really makes sense to do so before supplying an
__invert__
method to your class. (Note that byte-strings [ex:'\xff'
] do not support this operator, even though it is meaningful to invert all the bits of a byte-string.)〜
是 bitwise Replacterement operator 在Python中,它实际上是计算<<代码> -x -1 ,因此一个表看起来像
i = 0
它可以将s [0]
与s [len(len(len(len)) S)-1]
,对于i = 1
,s [1]
withs [len(s)-2]
。至于您的另一个问题,这对于一系列 bitwise hacks 很有用。
~
is the bitwise complement operator in python which essentially calculates-x - 1
So a table would look like
So for
i = 0
it would compares[0]
withs[len(s) - 1]
, fori = 1
,s[1]
withs[len(s) - 2]
.As for your other question, this can be useful for a range of bitwise hacks.
应该注意的是,在数组索引的情况下,
array [〜I]
等于REVERSED_ARRAY [i]
。可以将其视为从数组末尾开始的索引:One should note that in the case of array indexing,
array[~i]
amounts toreversed_array[i]
. It can be seen as indexing starting from the end of the array:除了是位补充操作员之外,
〜
也可以帮助恢复 boolean 值,尽管它不是常规bool
在此处键入使用numpy.bool _
。在此中解释了这一点,
有时会有时有用,例如,
〜
运算符用于清洁数据集并在没有NAN的情况下返回列。Besides being a bitwise complement operator,
~
can also help revert a boolean value, though it is not the conventionalbool
type here, rather you should usenumpy.bool_
.This is explained in,
Reversing logical value can be useful sometimes, e.g., below
~
operator is used to cleanse your dataset and return you a column without NaN.在实践中,我唯一使用的是
numpy/pandas
。例如,使用.isin()
dataframe方法。在文档中,他们显示了这个基本示例
,但是如果您想要所有行不在 [0,2]中怎么办?
The only time I've ever used this in practice is with
numpy/pandas
. For example, with the.isin()
dataframe method.In the docs they show this basic example
But what if instead you wanted all the rows not in [0, 2]?
解释为什么
-X -1
通常是正确的(对于整数)有时(示例),人们是〜运算符的数学行为感到惊讶。例如,他们可能认为,而不是评估
-19
,而是〜18
的结果应为13
(因为bin (18)
给出'0b10010'
,反转位将给出'0b01101',它代表13
- 对吗?)。或者,也许他们可能会期望237
(将输入视为已签名的8位数量),或其他一些与较大整数大小相对应的其他正值(例如机器单词大小)。请注意,在这里,签名位对位的解释
11101101
(被视为未签名,给出237
)是...-19
。大量位也会发生同样的情况。实际上,只要我们使用至少6位,并将结果视为签名,我们就会得到相同的答案:-19。只要我们使用足够的位并将结果处理为签名,就可以对所有输入进行数学规则 - 否定,然后减去一个。
从概念上讲,在Python中,数字使用任意数量的位。根据表示数字所需的内容,该实现将自动分配更多空间。 (例如,如果该值将“适合”一个机器单词,则仅使用一个词;数据类型会抽象将数字扩展到Infinity的过程。)它也没有任何单独的Unsigned-Integer类型;整数只是在Python中签名。 (毕竟,既然我们无法控制使用的内存量,那么拒绝访问负值的意义是什么?)
这打破了来自C环境的许多人的直觉,可以说是最好的实践仅使用无符号类型进行位操作,然后以后应用2s补充解释(并且仅在适当的情况下;如果将值视为“标志”组,则不太可能有意义的解释)。但是,Python的实现
〜
与其其他设计选择一致。如何强制无符号行为
如果我们想获得
13
,237
或其他类似的东西, 外部机制指定要倒入多少位。 (同样,18
从概念上讲,任意许多在其二进制表示中以任意数量的二进制表示;反转它们会导致领先1的某些东西;并在2s中解释这一点补充将产生负面的结果。)最简单的方法是简单地掩盖那些任意多的位。要从Inverting
18
获得13
,我们想要5位,因此我们用0b11111
,即31。原始行为的接口):另一种方式,根据安德鲁·詹金斯(Andrew Jenkins)在链接的示例问题上的回答,是直接用掩码XOR。有趣的是,我们 使用XOR来处理默认的任意推荐情况。我们只需使用任意尺寸的掩码,即一个整数,从概念上讲,其二进制表示中有任意数量的
1
位 - 即,-1 -1
。因此:但是,使用这样的XOR将为负面的
value
提供奇怪的结果 - 因为所有那些任意的模数设置位“之前”(在更重要的位置)(在更重要的位置上)未清除:Explaining why
-x -1
is correct in general (for integers)Sometimes (example), people are surprised by the mathematical behaviour of the ~ operator. They might reason, for example, that rather than evaluating to
-19
, the result of~18
should be13
(sincebin(18)
gives'0b10010'
, inverting the bits would give '0b01101' which represents13
- right?). Or perhaps they might expect237
(treating the input as signed 8-bit quantity), or some other positive value corresponding to larger integer sizes (such as the machine word size).Note, here, that the signed interpretation of the bits
11101101
(which, treated as unsigned, give237
) is...-19
. The same will happen for larger numbers of bits. In fact, as long as we use at least 6 bits, and treat the result as signed, we get the same answer: -19.The mathematical rule - negate, and then subtract one - holds for all inputs - as long as we use enough bits, and treat the result as signed.
In Python, conceptually, numbers use an arbitrary number of bits. The implementation will allocate more space automatically, according to what is necessary to represent the number. (For example, if the value would "fit" in one machine word, then only one is used; the data type abstracts the process of sign-extending the number out to infinity.) It also does not have any separate unsigned-integer type; integers simply are signed in Python. (After all, since we aren't in control of the amount of memory used anyway, what's the point in denying access to negative values?)
This breaks intuition for a lot of people coming from a C environment, in which it's arguably best practice to use only unsigned types for bit manipulation and then apply 2s-complement interpretation later (and only if appropriate; if a value is being treated as a group of "flags", then a signed interpretation is unlikely to make sense). Python's implementation of
~
, however, is consistent with its other design choices.How to force unsigned behaviour
If we wanted to get
13
,237
or anything else like that from inverting the bits of18
, we would need some external mechanism to specify how many bits to invert. (Again,18
conceptually has arbitrarily many leading 0s in its binary representation in an arbitrary number of bits; inverting them would result in something with leading 1s; and interpreting that in 2s complement would give a negative result.)The simplest approach is to simply mask off those arbitrarily-many bits. To get
13
from inverting18
, we want 5 bits, so we mask with0b11111
, i.e., 31. More generally (and giving the same interface for the original behaviour):Another way, per Andrew Jenkins' answer at the linked example question, is to XOR directly with the mask. Interestingly enough, we can use XOR to handle the default, arbitrary-precision case. We simply use an arbitrary-sized mask, i.e. an integer that conceptually has an arbitrary number of
1
bits in its binary representation - i.e.,-1
. Thus:However, using XOR like this will give strange results for a negative
value
- because all those arbitrarily-many set bits "before" (in more-significant positions) the XOR mask weren't cleared:我正在求解此 leetcode问题我遇到了这个美丽的解决方案一个名为 zitao wang 。
在不使用Divison的情况下找到所有剩余数字的产品
问题都像这样,
对于给定数组中的每个元素, 通过使用循环。他使用
〜
即时计算左产品和右产品I was solving this leetcode problem and I came across this beautiful solution by a user named Zitao Wang.
The problem goes like this for each element in the given array find the product of all the remaining numbers without making use of divison and in
O(n)
timeThe standard solution is:
His solution uses only one for loop by making use of. He computes the left product and right product on the fly using
~
我在Tilde操作员中发现的一种用途是将分数从某些碱基转换为基础10。
例如,假设您要将0.01从base-5转换为10。这样做的公式应该看起来像:
(0 * 5^0) +(0 * 5^-1) +(1 * 5^-2)
我们不需要打扰计算整数部分,但是如果我们确实需要,代码看起来像这样:
integer = sum(digit *(5 ** exp),exp,digit枚举(cretversed(str(integer))))
我们首先将整数反转因为最小的指数在整数的末端,即计算(x * 5^n) +(x * 5^n-1) +(x * 5^n-2)...
至于分数,最大的指数是分数的开始,因此我们不需要扭转整数。从0开始
。 。 EXP+1))。
* - ( sum(数字 *(5 ** 〜i)用于EXP,枚举(str(分数))中的数字
当基本中的符号不是数字时,该方法特别有用A,B,C,D和E分别表示0、1、2、3和4。
One use I've found for the tilde operator is for converting a fraction from some base into base-10.
For instance, let's say you want to convert 0.01 from base-5 to base-10. The formula for doing so should look like this:
(0 * 5^0) + (0 * 5^-1) + (1 * 5^-2)
We don't need to bother with calculating the integer part, but if we did need to, the code could look like this:
integer = sum(digit * (5 ** exp) for exp, digit enumerate(reversed(str(integer)))
We reverse the integer first because the smallest exponents are at the end of the integer part i.e. the calculation goes (x * 5^n) + (x * 5^n-1) + (x * 5^n-2) ...
As for the fraction, the largest exponent is as the start of the fractional part. So we don't need to reverse the integer. But if we try to use the
enumerate
method again, it'll only generate the positive numbers from 0 onwards.What we can do instead is
for exp, digit in enumerate(str(fraction))
, we can multiplydigit
by5 ** -exp
. We need to subtract one from-exp
so that 0 turns into -1, 1 turns into -2, and so on, so we can writedigit * (5 ** -(exp+1))
. We can replace-(exp+1)
with simply~i
for the below code:fraction = sum(digit * (5 ** ~i) for exp, digit in enumerate(str(fraction))
This approach is particularly useful when the symbols in a base aren't numbers e.g. a base-5 system that uses a, b, c, d, and e to represent 0, 1, 2, 3, and 4 respectively.
Quote from the docs
Just to complete things further, the tilde operator is documented for integers at
这对我来说很清楚。我有点困惑,因为在Python Integers中,默认情况下是任意精度,与C通常具有32或64位的整数大小不同,因此很难理解二元操作在Python中的含义。
关键洞察力的一部分是,在两个补充中,您可以扩展:
当然,Python并没有无限地存储许多一个或零的零件。在内存中:至少对于大整数而言,必须做什么是存储一个标志位和其余部分。然后,当您做
〜
时,它只是翻转符号位和其他位。例如,考虑在2的补充中考虑适合3位的整数:但是,其中一些值也可以用两个位而不是三位表示:
但是无论我们用来代表每个整数,
〜
结束了多少位只要我们以无限的许多同一符号数字扩展,就会给出相同的-X-1
结果。Quote from the docs
Just to complete things further, the tilde operator is documented for integers at https://docs.python.org/3.12/library/stdtypes.html#bitwise-operations-on-integer-types
This clear's things up for me a bit. I was a bit confused because in Python integers are arbitrary precision by default, unlike C where we usually have integer sizes like 32 or 64 bits, so it is a bit hard to understand what binary operations mean in Python.
Part of the the key insight is that in two's complement you can extend:
Of course, Python doesn't store infinitely many one's or zeros in memory: what it must do, at least for large integers, is to store one sign bit and the rest of the bits. Then when you do
~
it just flips both the sign bit and the other bits. E.g. consider integers that fit into 3 bits in 2's complement:But some of those values can also be represented by two bits instead of three:
but no matter how many bits we use to represent each integer,
~
ends up giving the same-x-1
result anyways, so long as we extend with infinitely many of the same sign digit.它称为二进制的补充(〜),
它返回了一个人的二进制文件的补充。它翻转了碎片。 2的二进制为00000010。它的补充是11111101。
这是-3的二进制文件。因此,这将导致-3。同样,〜1导致-2。
输出:
2
再次,一个人的补充-3是2。
it's called Binary One’s Complement (~)
It returns the one’s complement of a number’s binary. It flips the bits. Binary for 2 is 00000010. Its one’s complement is 11111101.
This is binary for -3. So, this results in -3. Similarly, ~1 results in -2.
Output :
2
Again, one’s complement of -3 is 2.
这是较小的用法是tilde ...
上面的代码来自“手机学习”,
您使用tilde(〜标志)作为替代 - 符号索引标记,
就像您使用的sigus一样 - 是用于整数索引
)
ex
print(array [〜1])
This is minor usage is tilde...
the code above is from "Hands On Machine Learning"
you use tilde (~ sign) as alternative to - sign index marker
just like you use minus - is for integer index
ex)
is the samething as
print(array[~1])