Python 简化'if…elif..else'条件
如果我有多个条件(嵌套和/或其他)和布尔值(要么<代码>假代码>要么<代码>真代码>)输出;如何进一步简化代码,使其更高效、更全面、更优雅 例如,在下列情况下:Python 简化'if…elif..else'条件,python,dictionary,flags,Python,Dictionary,Flags,如果我有多个条件(嵌套和/或其他)和布尔值(要么假要么真)输出;如何进一步简化代码,使其更高效、更全面、更优雅 例如,在下列情况下: if condition_1: if condition_2: # do one thing pass elif condition_3: # do another thing pass else: # do a third thing pass
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']}
如果我看了这篇文章:
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')
如果能有效地使用“if”、“elif”和“else”,那么使用“if”、“elif”和“else”也不错。但总的来说,你的问题的答案实际上取决于个人情况 尽管如此,一种方法是将您的条件放入
dict
(如您在标记中突出显示的)
以下是几个例子:
作为命令
:
返回:
Three
25
或在函数的情况下:
x = 5
if x in conditions.keys():
func = conditions[x]
print(func(x))
返回:
Three
25
使用函数类似于开关…案例:
为了使其更加清晰,并具有类似于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
函数装饰器(包装器)
因此,为了解决您添加的示例,我们可以执行以下操作:
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
首先,我们需要一个通用开关/机箱装饰器:
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.
根据条件(生成器对象)评估图元
将元素与相应的评估结果(生成器对象)匹配
现在,我们可以积极地调整输出(丢弃None
vlues)并创建一个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
打印(aflag)#`myDict`值中没有'a'。
---------------------------------------------------------------------------
NameError回溯(最近一次呼叫上次)
在()
24
--->25份印刷品(aflag)
NameError:未定义名称“aflag”
注意:在现有结构下,如果条件返回False
,将在名称空间中创建一个变量,并为其赋值False
希望这有帮助 这里的代码尽可能简单 压缩的一种方法是将最后一个分支更改为:
elif flag2:
if flag3:
do a fourth thing
到
可以对标志使用迭代器。字典也可以工作,这取决于你的标志是什么,但是如果你的标志是像
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
您考虑过重构吗?一个编写良好的函数应该做一件事,您有三个标志这一事实表明这段代码至少要做三件事,这给测试、代码可读性等带来了很多麻烦
是否确定无法将其重构为三个或更多方法,请检查开头的标志并启动相应的方法。您可以使用dict:
d = { (False, False, False) : f1,
(False, False, True) : f2,
(False, True, False) : f3,
(False, True, True) : f4
...
然后调用d[(flag1,flag2,flag3)]()
这是如果您需要工业量的if/else,否则请尝试进行正确的简化
当然,如果您测试的是同一个输入变量,或者应用同一个函数和不同的参数作为输出,那么您可以通过使用实际数据替换布尔值和函数来简化更多。您能给我们一个示例
标志吗
?您需要嵌套标志吗?或者您可以像这里那样设置4个不同的标志吗?为你的标志做一个真值表,看看哪些值会导致相同的结果。也许你会发现路径比你想象的要少。@Bahrom我添加了一个简单的例子:)有一个示例标志和/或一个示例可能会有所帮助。为什么不使用dict
?消除了对发电机的需求,使其循环更加有序。你不同意吗?@PouriaHadjibagheri我同意一个dict
,我只是在想-假设你的标志是x==1,x==2,x==3,y==5
。现在,它们可以计算为True
或False
,但字典键必须是唯一的。我想你可以用这样的方法来解决这个问题:{True:[first\u action,second\u action,etc.],False:[fifth,etc.]}
。我认为这取决于你在这一点上提供了什么样的标志。我明白你的观点,它是有效的。但我倾向于尽可能避免迭代,即使是在生成器中。在您提到的场景中,还可以交换键和项,或者将它们作为字符串值放入,并使用exec
实现它们。看看我的例子。因为它是一个函数,所以exec
的使用将变得非常简单和高效。是的,我实际上很想使用dict
她
d = { (False, False, False) : f1,
(False, False, True) : f2,
(False, True, False) : f3,
(False, True, True) : f4
...