一种在python中编写IF语句以跳过None的干净方法?

时间:2018-08-02 02:40:01

标签: python python-3.x if-statement

我有一个函数,其中有时一个参数可以为none,我想将其与另一个对象进行比较。但是,如果我尝试调用对象属性,即使两个对象都不是,脚本也会在None上引发异常(请参见下面的示例)。

def do_animals_make_same_sound(first_animal, second_animal):
    if first_animal.sound = second_animal.sound:
        print('Yes they do!')

但是如果两个动物都不是,则当我希望它打印时会抛出异常('是的,他们这样做!'),但是看来我必须写一个非常难看的If语句:

def do_animals_make_same_sound(first_animal, second_animal):
    if (first_animal is None and second_animal is None) or (first_animal is not None and first_animal.sound == second_animal.sound):
        print('Yes they do!')

有更好的方法吗?

4 个答案:

答案 0 :(得分:2)

以下代码更清晰,恕我直言:

def do_animals_make_same_sound(first_animal, second_animal):
    # early return if one of the two animals is missing, ensure both exist
    if not (first_animal and second_animal):
        return
    if first_animal.sound == second_animal.sound:
        print('Yes they do!')

ref:Avoid Else, Return Early

答案 1 :(得分:0)

这不是很好,但是一种方法可以是使用带有默认值的getattr,因此None(以及没有所需属性的任何其他内容)的行为就好像它具有默认值作为其值属性。例如:

if first_animal.sound == second_animal.sound:

可以成为:

if getattr(first_animal, 'sound', None) == getattr(second_animal, 'sound', None):

我实际上不建议这样做,因为它会默默地忽略错误。在实际代码中,我几乎总是让AttributeError传播;在任何合理的情况下,我都不认为None是“某物”的可接受替代,其中“某物”具有特定的行为或属性;如果调用方正在传递None,则几乎可以肯定是一个错误,不应将其忽略。

答案 2 :(得分:0)

我认为,如果对象之一为“无”,那么您首先必须了解什么意思。基本上有三种情况:

  1. 一个或两个对象都不是

  2. 一个或两个对象没有sound属性

  3. 都具有sound属性

对于#1,我假设它应该抛出错误,因为实际上没有比较。如果两个对象均为“无”,则代码将打印“是”。

对于#2,您可以使用ShadowRanger的建议,如果两个对象都具有None作为sound属性,并且您认为这是正常行为,请使用ShadowRanger的解决方案。

对于#3,只需进行常规比较

def do_animals_make_same_sound(first_animal, second_animal):
    if not first_animal or not second_animal:
        print("One of the objects is None")
    elif getattr(first_animal, 'sound', None) == getattr(second_animal, 'sound', None):
        print("Yes, they do!")

答案 3 :(得分:0)

如果这是足够通用的模式,我将使用装饰器来专门捕获None案例并对其进行处理。这使逻辑脱离了功能。但是您需要确切地定义None在这里的含义...您可以为两者都通过None,这有点奇怪,但是仅为其中一个通过None是不合法的。无论如何,装饰器都是一种以简洁的方式抽象出一些常见逻辑的好方法。

def NoNone(f):
    @functools.wraps(f)
    def _no_none_func(*args, **kwargs):
        if args[0] == None and args[1] == None:
            print('Both are None')
            return 
        return f(*args)
    return _no_none_func

@NoNone
def do_animals_make_same_sound(first_animal, second_animal):
    if first_animal.sound == second_animal.sound:
        print('Yes they do!')
    else:
        print("No they don't!")