1

这两个函数做同样的事情。

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() 创建的行越多,嵌套的 if 越多,这与 PEP8 的行长限制 78 冲突。

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

哪个更pythonic?

4

5 回答 5

7

Pythonic 代码的原则之一是“平面优于嵌套”。在此基础上,我会说function2()客观上更 Pythonic。这可以在PEP-20: The Zen of Python中看到:

Python之禅

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!

这可以通过import this在 Python 解释器中键入来查看。

于 2016-06-03T08:26:30.737 回答
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

当然,这可以进一步改进

于 2016-06-03T08:35:07.783 回答
1

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

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

于 2016-06-03T08:52:23.737 回答
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]
于 2016-06-03T09:18:47.883 回答
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可以去。

于 2020-05-09T15:34:52.390 回答