这是第一次使用python中的按位运算,但也有奇怪的(对我来说)语法。
for i in range(2**len(set_)//2):
parts = [set(), set()]
for item in set_:
parts[i&1].add(item)
i >>= 1
对于上下文,set_只是一个包含4个字母的列表。
这里有一点要打开包装。首先,我从未见过[set(), set()]
。我必须使用错误的关键字,因为我无法在文档中找到它。看起来它在pythontutor中创建了一个矩阵,但我不能肯定地说。其次,虽然parts[i&1]
是切片操作,但我并不完全确定为什么需要按位操作。例如,0& 1应该是1而1和1应该是0(携带一个),所以二进制10(或十进制2)?最后,最后的按位操作完全令人困惑。我认为正确的转变与除以2(我希望)相同,但为什么i>>=1
?我不知道如何解释这一点。任何指导都将真诚地感谢。
答案 0 :(得分:2)
[set(), set()]
创建一个由两个空集组成的列表。
0& 1为0,1& 1为1.按位运算没有进位。因此,parts[i&1]
指的是i
为偶数时的第一组,i
为奇数时的第二组。
i >>= 1
向右移动一位(实际上与除以2相同),然后将结果分配回i
。它与使用i += 1
递增变量的基本概念相同。
内循环的作用是根据_set
的位将i
的元素划分为两个子集。如果外部循环中的限制只是2 ** len(_set)
,则代码将生成所有可能的此类分区。但是,由于该限制被除以2,因此只生成了一半可能的分区 - 如果没有更多的上下文,我无法猜出这可能是什么意思。
答案 1 :(得分:1)
我从未见过[set(),set()]
这不是什么有趣的东西,只是一个包含两个新集的列表。所以你已经看过了,因为它不是新的语法。只是一个列表和构造函数。
parts[i&1]
这将测试i
的最低有效位,并选择parts[0]
(如果lsb为0)或parts[1]
(如果lsb为1)。什么都不像切片,只是简单的索引到列表中。你得到的东西是一个集合,.add(item)
做了显而易见的事情:在选择的任何一个集合中添加一些内容。
但为什么
i>>=1
?我不知道如何解释
取i
中的位并将它们向右移动一个位置,放下旧的lsb,然后保持符号。有点像这样
当然,除了在Python中你有任意精度的整数,所以它需要长而不是8位。
对于正数,有关复制符号的部分无关紧要。
您可以将右移1乘以地板除以2(这与截断不同,负数向负无穷大舍入,例如-1 >> 1 = -1
),但这种解释通常更难理解
无论如何,这里使用它的方式只是循环遍历i
的位,逐个从低到高测试它们的方法,但不是改变它测试的位而是移动位我希望每次都能测试到相同的位置。