如果我有多个条件(嵌套和/或其他)与布尔(False
或True
)输出;我怎样才能进一步简化代码并使其更高效,更全面,更优雅?
例如,在以下情况下:
if condition_1:
if condition_2:
# do one thing
pass
elif condition_3:
# do another thing
pass
else:
# do a third thing
pass
elif condition_2:
if condition_3:
# do a fourth thing
pass
等等。
这是我的考试项目,所以没有得到太多帮助,我会尝试解释我的代码应该做什么。 我基本上想要浏览一个数据集,寻找不同的东西。让我们说它是一本字典,如下:
myDict = {'a': ['b', 'c'], 'b': ['c', 'd']}
如果我通过dict:
for item, element in myDict.items():
for letter in element:
if letter == 'd':
dflag = True
if letter == 'c':
cflag = True
if cflag:
if dflag:
print('cd!')
else:
print('only c')
答案 0 :(得分:1)
如果高效完成,使用'if','elif'和'else'也不错。但总的来说,你的问题的答案实际上取决于个人情况。
然而,话虽如此,一种方法是将你的条件置于dict
内(如你自己在标签中所强调的那样)。
以下是一些例子:
dict
:conditions = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: lambda x: x**2 # Can be substituted with actual functions defined elsewhere.
}
x = 3
if x in conditions.keys():
print(conditions[x])
返回:
Three
或在函数的情况下:
x = 5
if x in conditions.keys():
func = conditions[x]
print(func(x))
返回:
25
switch...case
的函数:为了使它更清晰,并且有switch...case
语句,你可以这样做:
def switch(case):
conditions = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: lambda x: x**2
}
return condition[case] if case in conditions else False
它是这样运行的:
>>> print(switch(2))
2
或不存在的项目:
>>> print(switch(6))
False
switch...case
函数装饰器(包装器)因此,为了解决您添加的示例,我们可以执行以下操作:
首先我们需要一个通用的开关/案例装饰器:
def switch_case(switch):
def switcher(func):
def case(case):
return switch[case](case) if case in switch else None
return case
return switcher
然后我们需要一个我们条件的字典,这是你的例子中给出的字典:
# Define the conditions in a dict.
conditions = {
'd': lambda x: True if 'd' else False, # You can say: True if 'a' or 'b' else False
'c': lambda x: True if 'c' else False
}
现在我们根据您的条件创建一个装饰的开关案例函数:
@switch_case(conditions)
def my_conditions(case):
return case
然后我们指定元素,或者从文件,数据库或任何东西中读取它们:
# Elements to be tested as string.
# It can be any flattened (not nested) iterable (str, tuple, list, numpy.array, etc.)
myDict = {'a': ['b', 'c'], 'b': ['c', 'd']}
elements = sum(myDict.values(), []) # Returns a flattened lists of values.
根据条件(生成器对象)评估元素。
verdicts = map(my_conditions, elements)
将元素与相应的评估结果(生成器对象)匹配。
status = zip(elements, verdicts)
现在我们可以正面调节输出(丢弃None
线索)并创建一个dict
,其中键是元素,值是其条件的状态。
passed = {key+'flag': val for key, val in status if val is not None}
print(passed)
# output: {'cflag': True, 'dflag': True}
此时,您可以按原样使用dict;但是,如果您坚持将其添加到命名空间,请按以下方式进行操作:
# Rename values and add them to the name space.
locals().update(passed)
最后,让我们测试并确保本地命名空间中存在值(注意我们之前没有实现过任何这些名称)。因此,如果条件为序列中的特定字符返回True
值,则会创建一个变量:
>>> print(dflag) # We had 'd' in `myDict` values.
True
另一方面,如果条件返回None
,则命名空间中没有值。
>>> print(aflag) # We didn't have 'a' in `myDict` values.
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-25-26f7e9594747> in <module>()
24
---> 25 print(aflag)
NameError: name 'aflag' is not defined
注意:在现有结构下,如果条件返回False
,将在命名空间中创建 变量,并为其分配值{{1 }}
希望这会有所帮助。
答案 1 :(得分:0)
这里的代码就像你能得到的一样简单。
您可以压缩的一种方法是更改最后一个分支:
elif flag2:
if flag3:
do a fourth thing
到
elif flag2 and flag3:
do a fourth thing
答案 2 :(得分:0)
您可以在标志上使用迭代器。字典也可以工作,具体取决于你的标志是什么,但是如果你的标志像x==1, y==10, z=='a'
那样可以全部评估为True
或False
仅(因为密钥只能是唯一的)。如果你的标志是a == b
的形式,你可能不得不使用某种迭代器。
def f(): print('f')
def g(): print('g')
def h(): print('h')
y = 3
x = 2
flags = [
# Outer condition
(y==1, (
# Inner conditions and actions
(x==1, f), (x==2, g), (x==3, h)
)),
(y==3, (
(x==1, g), (x==2, f), (x==3, h)
))
]
# Using next ensures that the rest of the flags/actions aren't even evaluated,
# the same way an if/elif would work
_, inner_flags_and_actions = next(
(flag, inner) for (flag, inner) in flags if flag
)
_, action = next(
(flag, action) for (flag, action) in inner_flags_and_actions if flag
)
# By now you have reached the action you want to take.
action()
打印:f
答案 3 :(得分:0)
你考虑过重构吗?一个编写良好的函数应该做一件事,事实上你有三个标志表明这个代码块将至少做三件事,这给测试,代码可读性等带来了很多麻烦。
您确定无法将其重构为三个或更多方法,请检查开头的标记并启动相应的方法。
答案 4 :(得分:0)
您可以使用词典:
d = { (False, False, False) : f1,
(False, False, True) : f2,
(False, True, False) : f3,
(False, True, True) : f4
...
然后拨打d[(flag1,flag2,flag3)]()
如果您需要工业数量的if / elses,否则只需尝试进行正确的简化。
当然,如果你再次测试相同的入口变量,或者使用不同参数作为输出应用相同的函数,那么你可以通过用实际数据替换布尔值和函数来进一步简化。