返回元组或无的函数:如何很好地调用该函数?

Posted

技术标签:

【中文标题】返回元组或无的函数:如何很好地调用该函数?【英文标题】:Function returning a tuple or None: how to call that function nicely? 【发布时间】:2011-03-27 19:06:23 【问题描述】:

假设如下:

def MyFunc(a):
  if a < 0:
    return None
  return (a+1, a+2, a+3)

v1, v2, v3 = MyFunc()
# Bad ofcourse, if the result was None

定义一个返回元组但又可以很好地调用的函数的最佳方法是什么。目前,我可以这样做:


r = MyFunc()
if r:
  v1, v2, v3 = r
else:
  # bad!!
  pass

我不喜欢的是我必须使用单个变量然后解压它。

另一个解决方案是我可以让函数返回一个满是 None 的元组,以便调用者可以很好地解包....

谁能推荐更好的设计?

【问题讨论】:

哪个更pythonic - 返回None或返回一个无元组? 【参考方案1】:

如何提高ArgumentError?然后你可以try调用它,如果参数错误则处理异常。

所以,类似:

try:
    v1, v2, v3 = MyFunc()
except ArgumentError:
    #deal with it

另外,请参阅 katrielalex's answer 以了解如何使用 ArgumentError 的子类。

【讨论】:

这很好,但我总是担心引发和处理异常的开销【参考方案2】:

这应该很好用:

v1, v2, v3 = MyFunc() or (None, None, None)

MyFunc()返回一个元组时,将其解包,否则将替换为None的三元组。

【讨论】:

我看不出这比返回 Nones 的元组更好。 如果更好,可能是因为它不需要改变函数的内容。 recursive:虽然语法看起来不错,但如果您需要多次调用 MyFunc() 则效率不高。正如建议的那样,最好返回 Nones 的元组 @lallous:是的,我同意这一点,但问题是明确地寻找其他解决方案。 这个结构的问题是,如果我有多个函数调用,我将不得不重复这个结构,这不是很好阅读不止一次......【参考方案3】:

recursive 有一个真正优雅和 Pythonic 的解决方案。但是:为什么要返回None? Python 有一种处理错误的方法,那就是引发异常:

class AIsTooSmallError( ArgumentError ): pass

然后

raise AIsTooSmallError( "a must be positive." )

这样做更好的原因是返回一个值表示您已完成处理并正在传回您的答案。如果您进行了一些处理,这很好,但如果您立即返回None,那就很愚蠢了。

【讨论】:

嘿。所以你是。但我继承了ArgumentError 是的,这可能是一个更好的选择 :) 您可能会争辩说,导致返回 None 的不是错误情况。可能只是该函数没有答案。 确实如此;这是一种语义论证。这将取决于代码的实际内容。 现在值得提出另一个问题。我还没有完全研究过,但是:Python 异常的成本是多少?或者换种说法,哪个更好: - 返回 (None, None, None) 或 - 抛出异常?【参考方案4】:

另一个解决方案是我可以让函数返回一个满是 None 的元组,这样调用者就可以很好地解包......

这有什么问题?一致性是一件好事。

【讨论】:

我同意。事实上,它维护了函数的返回签名。 +1 维护返回签名是静态的;) @Skilldrick:根据我的经验,一致的返回签名允许人们对愚蠢的细节和异常一无所知,从而提高了活力。但我只是懒惰。【参考方案5】:

如果您希望v1, v2, v3 对象存在并在发生错误时设置为默认值,请自行返回默认值。这将使调用代码更简单,不依赖调用者手动设置它们:

def MyFunc(a):
    if a < 0:
        # can't use a negative value; just return some defaults
        return (None, None, None)
    return (a+1, a+2, a+3)

另一方面,如果默认返回不合适并且否定参数被认为是严重错误,则引发异常:

def MyFunc(a):
    if a < 0:
        # sorry, negative values are unacceptable
        raise ValueError('cannot accept a negative value')
    return (a+1, a+2, a+3)

第三困难中,有时在返回单个对象时返回None 可能更可取,例如re 模块的search()match() 函数。它以某种方式介于前两种情况之间,因为匹配失败是预期的结果,而默认返回对象无论如何都不是很有用。

【讨论】:

【参考方案6】:

这与上一个答案类似。您可以返回一个对象实例或 None

def MyFunc(a):
    class MyFuncClass(object):
        def __init__(self, **kwargs):
            self.__dict__.update(kwargs)
    if a < 0:
        return None
    return MyFuncClass(one=a+1, two=a+2, three=a+3)

o = MyFunc(1)
if o is not None:
    print o.one, o.two, o.three

【讨论】:

以上是关于返回元组或无的函数:如何很好地调用该函数?的主要内容,如果未能解决你的问题,请参考以下文章

python3里函数怎么样使用元组或字典作为参数调用(复制他人博客)

遍历列表元组或字符串的函数enumerate

数据库查询学习心得

python apply()函数

如何使用嵌套元组或 HList 处理具有 Slick 的 > 22 列表?

如何在 Python 中创建具有两列作为元组或 Pandas 数据框的单个变量?