如果没有返回值,则不调用函数

2024-04-26 18:11:31 发布

您现在位置:Python中文网/ 问答频道 /正文

假设有一个函数可以返回某些对象或不返回任何对象:

def foobar(arg):
   if arg == 'foo':
       return None
   else:
       return 'bar'

现在你调用这个方法,你想对这个对象做点什么,在这个例子中,我得到了一个str,所以我可能想调用upper()函数。 现在有两种情况会发生,第二种情况会失败,因为没有一种方法upper()

^{pr2}$

当然,现在很容易解决:

tmp = foobar('foo')
if tmp is not None:
    tmp.upper()
# or
try:
    foobar('foo').upper()
except ArgumentError:
    pass
# or
caller = lambda x: x.upper() if type(x) is str else None
caller(foobar('foo'))

但是异常处理可能不够具体,我可能会捕捉到一个可能很重要的异常(=调试变得更困难),而第一个方法是好的,但可以产生更大的代码,第三个选项看起来相当不错,但你必须对所有可能的函数都这样做,所以方法一可能是最好的。在

我想知道有没有语法糖可以很好地处理这个问题?在


Tags: 对象方法函数nonereturniffoois
3条回答

自从这个问题得到了回答,有几个新的发展使这个模式变得更加容易。在

pymaybe包允许您简单地用maybe包装值来静默地传播None值:

from pymaybe import maybe
maybe(foobar('foo')).upper()

这与Martijn Pieters的答案非常相似,只是它保留了None值,而不是用空字符串替换它们,并且在存在多个假值的情况下,它将更加健壮。在

此外,在PEP 505上似乎有一个标准跟踪草案建议,它希望将类似于C的{}访问器的语法添加到语言本身。我不知道它有多大的支持,但它是一个地方寻找可能的进一步增强。在

另一种方法-第一个/第三个选项可以打包:

def forward_none(func):
    def wrapper(arg):
        return None if arg is None else func(arg)
    return wrapper

当函数和方法在类中被使用的时候,它们仍然没有在类中使用它们的属性和方法:

^{pr2}$

我们也可以用它来装饰:

@forward_none
def do_interesting_things(value):
    # code that assumes value is not None...

do_interesting_things(None) # ignores the original code and evaluates to None
do_interesting_things("something") # as before decoration

虽然在实践中,如果必须的话,我可能会按照玛蒂恩的建议去做。我会尽力避免这样做;进入这种情况是一种代码气味,表明我们应该首先引发一个异常,而不是返回{}。:)

您可以使用:

(foobar('foo') or '').upper()

括号内的表达式返回一个字符串,即使foobar()返回错误值。在

这会导致空字符串替换None。如果您的代码依赖于None留在原位,那么您的最佳选择仍然是仅在返回值不是None的情况下使用单独的if语句来调用.upper()。在

相关问题 更多 >