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
...