嵌套如果 - 什么更像Pythonic?

时间:2016-06-03 08:25:25

标签: python if-statement nested indentation pep

两个功能都做同样的事情。

def function1(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    r = None

    if a:
        r = a
        if b:
            r = b
            if c:
                r = c
            else:
                print("c not set.")
        else:
            print("b not set.")
    else:
        print("a not set.")

    return r



def function2(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    r = None

    if not a:
        print("a not set.")
        return r

    r = a
    if not b:
        print("b not set.")
        return r

    r = b
    if not c:
        print("c not set.")

    r = c
    return r

function1()创建非常长的行,如果嵌套的话就越多,这与PEP8的行长度限制为78.

function2()可能更难阅读/理解,并且有更多的return语句。线长在这里没问题。

哪一个更像pythonic?

5 个答案:

答案 0 :(得分:4)

Pythonic代码的一个原则是" flat比嵌套"更好。在此基础上,我会说Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! 客观上更像是Pythonic。这可以在PEP-20: The Zen of Python

中看到
  

Python的禅宗   

import this

通过在Python解释器中键入new可以看出这一点。

答案 1 :(得分:2)

正如@ Will的回答所示,平坦更好。但是,无论如何代码看起来都不是很漂亮。如何更紧凑的代码?

从@ Will的回答中查看这些引用:

  

可读性计数。

     

美丽胜过丑陋。

from collections import OrderedDict
def function3():
    my_dictionary=OrderedDict()
    my_dictionary['a'] = self.get_a()
    my_dictionary['b'] = self.get_b()
    my_dictionary['c'] = self.get_c()
    # ...
    r = None

    for name in my_dictionary.keys():
        value = my_dictionary[name]
        if not value:
            print("%s not set." % name)
            return r
        r = value
    return r

当然,这可以进一步改善

答案 2 :(得分:1)

您可以使用andor运算符的评估规则,例如:

>>> None or 4 or None or 5
4

>>> 4 and 5
5

所以你有类似的东西:

def function3(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    return (a and b and c) or (a and b) or a or None

我建议您从逻辑代码中分解I / O.

答案 3 :(得分:0)

我建议下面显示的function_4以及问题(非理性工作!)函数和DomTomCat的答案之一:

#! /usr/bin/env python
from __future__ import print_function
from collections import OrderedDict  # Only used in function_3


def function_4(self):
    """Iterate over call results in FIFO on False or if sequence
    exhausted, return None or previous value if that evaluates to true."""

    functors = (
        self.get_a,
        self.get_b,
        self.get_c,
    )
    request_targets = (
        'a',
        'b',
        'c',
    )
    response_value = None
    for functor, request_target in zip(functors, request_targets):
        current_response = functor()
        if not current_response:
            print(request_target, "not set.")
            return response_value
        else:
            response_value = current_response

    return response_value


class Foo(object):
    """Mock the thingy ..."""
    def __init__(self, a, b, c):
        self._a, self._b, self._c = a, b, c

    def __repr__(self):
        return (
            "Foo(" + str(self._a) + ", " + str(self._b) + ", " +
            str(self._c) + ")")

    def get_a(self):
        return self._a

    def get_b(self):
        return self._b

    def get_c(self):
        return self._c


def function_1(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    r = None

    if a:
        r = a
        if b:
            r = b
            if c:
                r = c
            else:
                print("c not set.")
        else:
            print("b not set.")
    else:
        print("a not set.")

    return r


def function_2(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    r = None

    if not a:
        print("a not set.")
        return r

    r = a
    if not b:
        print("b not set.")
        return r

    r = b
    if not c:
        print("c not set.")

    r = c
    return r


def function_3(self):
    my_dictionary = OrderedDict()
    my_dictionary['a'] = self.get_a()
    my_dictionary['b'] = self.get_b()
    my_dictionary['c'] = self.get_c()
    # ...
    r = None

    for name in my_dictionary.keys():
        value = my_dictionary[name]
        if not value:
            print("%s not set." % name)
            return r
        r = value


def main():
    """"Drive the investigation."""
    fixtures = (
        (1, 42, 3.1415),
        (0, 42, 3.1415),
        (1, 0, 3.1415),
        (1, 42, 0),
    )
    functors = (
        function_1,
        function_2,
        function_3,
        function_4,
    )
    for fixture in fixtures:
        foo = Foo(*fixture)
        print("\nFixture:", foo)
        for i, functor in enumerate(functors, start=1):
            print("Functor[%d]:" % (i,))
            print(functor(foo))


if __name__ == '__main__':
    main()

在我的机器上,灯具在被调用时会产生以下行为/输出:

Fixture: Foo(1, 42, 3.1415)
Functor[1]:
3.1415
Functor[2]:
3.1415
Functor[3]:
None
Functor[4]:
3.1415

Fixture: Foo(0, 42, 3.1415)
Functor[1]:
a not set.
None
Functor[2]:
a not set.
None
Functor[3]:
a not set.
None
Functor[4]:
a not set.
None

Fixture: Foo(1, 0, 3.1415)
Functor[1]:
b not set.
1
Functor[2]:
b not set.
1
Functor[3]:
b not set.
1
Functor[4]:
b not set.
1

Fixture: Foo(1, 42, 0)
Functor[1]:
c not set.
42
Functor[2]:
c not set.
0
Functor[3]:
c not set.
42
Functor[4]:
c not set.
42
[Finished in 0.0s]

答案 4 :(得分:0)

这是我不删除打印语句所要做的

def function1(self):
    a = self.get_a()
    b = self.get_b()
    c = self.get_c()
    r = None

    inputValues = [a, b, c]
    setValues = [i for i in inputValues if i]
    for index, value in inputValues:
        if len(setValues) <= index or setValues[index] != value:
            print(f'{value} is not set.')
        else:
            r = value
    return r

function2看起来还不错。