我正在开发一个有趣的小python项目,我不得不尝试将我的If循环调整为Dictionary,但我只是不确定如何实现这个功能,因为我需要多个条件来测试。
我有6个布尔,(bool1-bool6),显然可以是T或F,和 我需要测试这些布尔值的每种可能组合,以便我可以告诉我的程序在哪里绘制图像。
有64种可能的组合。
我们可以用3个布朗来做到这一点简单,有3种布尔可能的组合。
如果我们想象1 =真且0 =假,那么可能的组合可以表示为。
000
001
010
011
100
101
110
111
表示这个的if循环,
if (bool1==false and bool2==false and bool3==false)
do stuff
elif (bool1==false and bool2==false and bool3==true)
do stuff
elif (bool1==false and bool2==true and bool3==false)
do stuff
and so on...
除非您能找到简化此过程的方法,(了解我需要检查所有可能的布尔组合),否则无需批评我的问题。我只是不确定如何从这里进步,并非常感谢一些帮助。
我写了一个64语句If Loop,我正在研究这个解决方案,虽然我和我都确定我的cpu更喜欢更快的方法。
答案 0 :(得分:1)
你有六个布尔变量bool1到bool6。
想要的是有点代表如下例:
101101
最左边的位代表bool6,最右边代表bool1。 所以你得到订单bool6,bool5,bool4,...,bool1。
现在,您为状态分配一个变量,由这些布尔变量表示:
state = bool6 << 5
state = state ^ (bool5 << 4)
state = state ^ (bool4 << 3)
state = state ^ (bool3 << 2)
state = state ^ (bool2 << 1)
state = state ^ (bool1)
您找到<<
here
现在发生的是,您定义了一个新的整数变量,由您的不同布尔值表示。
根据您的进一步do_something
实施,您可以像这样定义方法参数:
cases = {
0b000011 : "drawing parameter",
0b001011 : "drawing parameter",
0b111000 : "another drawing parameter",
}
其中,字典键是从000000
到111111
另外,您可以检查每个案例是否都有一个已定义的参数:
for n in range(1<<6):
if not n in cases:
raise LookupError('cases do not contain index %d' % n)
因此,稍后,您可以使用这些位表示,如下所示。
for c in cases:
if state == c: # if the checked case is equal to the state, then use the parameters
parameters = cases[c]
do_something(parameters)
答案 1 :(得分:0)
对于6个布尔值,有2 ^ 6个组合直接对应于从0
到2^6-1
的数字中的位。如果需要为单个函数调用定义特殊参数,可以通过使用参数列表或字典来解决此问题,然后使用每个参数调用该函数:
cases = {
0b000000: ((arg1a, arg2y), {'key1': kwarg1, 'key2': kwarg2}),
0b000001: ((arg1b, arg2x), {'key23': kwarg23, 'key7': kwarg7}),
# ...
0b111111: ((arg1a, arg2z), {'key4': kwarg4, 'key2': kwarg2}),
}
for n, (args, kwargs) in cases.items():
print("Test case {:d} ({:#08b}):".format(n,n))
test_fun(*args, **kwargs)
如果您不需要关键字参数,则可以轻松简化。
如果你需要做更多具体的事情,你可以在字典中使用lambdas而不是参数集:
cases = {
0b000000: lambda: test_fun(1,2, foo='bar'),
0b000001: lambda: test_fun(3,2, moo='bar'),
# ...
0b111111: lambda: test_fun(8,3, foo='bar'),
}
for n, fun in cases.items():
print("Test case {:d} ({:#08b}):".format(n,n))
fun()
您还可以将这些词典转换为列表,将dict索引转换为注释:
cases = [
# 0b000000
((arg1a, arg2y), {'key1': kwarg1, 'key2': kwarg2}),
# 0b000001
((arg1b, arg2x), {'key23': kwarg23, 'key7': kwarg7}),
# ...
# 0b111111
((arg1a, arg2z), {'key4': kwarg4, 'key2': kwarg2}),
]
for n, (args, kwargs) in enumerate(cases):
print("Test case {:d} ({:#08b}):".format(n,n))
test_fun(*args, **kwargs)
在所有情况下,我都会确保在cases
的定义后直接进行一致性检查,例如
# for the `cases` dictionary
for n in range(1<<6):
if not n in cases:
raise LookupError("dict variable cases does not contain %d" % n)
# for the `cases` list
assert(len(cases) == (1<<6))
如果您可以轻松地从索引编号中导出参数集,则可以避免定义测试用例的完整列表或字典,并且只需动态计算参数值:
for n in range(1<<6):
param1 = 23
if (n & (1<<0)):
param1 = 42
# ...
param6 = bool(n & (1<<5))
# ...
test_fun(param1, ..., param6)
或者您可以将参数生成逻辑放入生成器函数中,可选择使用(可能reversed()
)list
替换yield语句中的元组表达式。
def all_bool_tuples_from_bits(n):
for k in range(1<<n):
yield (bool(k&(1<<i)) for i in range(n))
print("Run test_fun with the arguments")
for args in all_bool_tuples_from_bits(6):
test_fun(*args)
print("Run test_fun with the arguments in explicit variables")
for p0, p1, p2, p3, p4, p5 in all_bool_tuples_from_bits(6):
test_fun(p0, p1, p2, p3, p4, p5)
print("Run test_fun with the arguments while numbering the test cases")
for n, args in enumerate(all_bool_tuples_from_bits(6)):
print("Test case {:d} ({:#08b}):".format(n,n))
test_fun(*args)
我希望这能为您提供一些想法。
关于CPU的使用情况,我不会担心只有64个不同的测试用例,每个测试用例都生成一个PDF文件,这个文件肯定会比迭代超过64个测试用例的CPU密集程度更高。
真正的担心是你可能忘记在那个巨大的if elif elif elif
构造中列出一个案例,而不是自己注意到这一点。因此,我希望使用代码让计算机确保每个组合都经过检查。对于6个布尔参数,我会使用生成器。
答案 2 :(得分:0)
int-to-binary方法很聪明,但没有概括。有一种更简单的方法可以推广到除Boolean之外的数据类型:
import itertools
for i in itertools.product((0, 1,), repeat=3):
... stuff ...
这将返回(0, 0, 0), (0, 0, 1) ... (1, 1, 1)
等元组。
您可以将未命名的第一个参数更改为任何可迭代 - xrange()
,set,array等 - 并将repeat
参数更改为所需的长度。适用于任何数据类型。