26

Python 在 MATLAB 中有任何等价的 nargout 吗?如果我们想保持返回参数的数量灵活,我发现 nargout 是一种非常简洁的方法。有没有办法可以找出请求了多少输出参数?类似于以下伪python代码:

def var_returns_func(a):
  """
  a is a 1D numpy array
  """
  if nargout==1: return a.sum()
  elif nargout==2: return a.sum(),a.std()

因此,如果我将此函数称为mean = var_returns_func(someNumPyarray),它应该返回一个值。但如果我称它为mean,std = var_returns_func(someNumPyarray),它应该返回 2 个值。

有没有一种 Pythonic 的方式来做到这一点?还是一种骇人听闻的方式?

4

5 回答 5

18

该函数无法知道返回值将要做什么,因此它无法知道需要多少个。您可以做的是将nargout作为参数传递给您的函数并使用它来决定返回什么:

def f(a, nargout=1):
    if nargout == 1:
        return "one value"
    elif nargout == 2:
        return "two", "values"
    else:
        raise ValueError, "Invalid nargout!"

这是作为 Python 哲学的“显式优于隐式”的示例。如果你想要两个论点,你必须明确地说你想要两个论点。在 Python 中不鼓励基于对未来的展望来隐含地做出决定以查看将要对结果做什么。完全有可能做a = f(x)并且想要在 a 中获得一个二元素元组。

对于像你这样的例子,有很多更好的方法。一种是刚做mean, std = a.mean(), a.std()的,或者更一般x, y = someFunc(a), otherFunc(a)的。如果通常需要这种特定的值组合,并且您不想复制两个操作共享一些昂贵的计算,请创建第三个函数,该函数清楚地返回和 do x, y = funcThatReturnsTwoThings(a)。如果它们做不同的事情,所有这些都是保持函数分离的显式方法。

于 2013-01-03T21:42:04.010 回答
11

我不能nargout在 MATLAB 中说话,因为我不知道它,我无法想象它应该如何正确使用。但是,您可能希望将视图更改为 Python 函数(或方法)的真正作用)。

实际上,Python 总是只返回一个值。或者它是 None,或者它是某个特定类型的单个值,或者它是该tuple类型的单个对象。

如果没有return命令,None则函数体结束则函数返回。这与您return在正文末尾或正文末尾不带参数显式编写相同return None

如果使用return NoneNone可以存储在变量中)或return不使用参数,None则返回给调用者。

如果你return singlesingle对象将返回给调用者。

如果你return v1, v2, v3,你实际上返回一个元组(v1, v2, v3)。它只是一个语法糖,你不需要写括号。

result1, result2, result3 = f()这种情况下,只是另一种语法糖。f()返回元组及其元素被自动提取到给定的变量。你实际上是这样做的:

result1, result2, result3 = (v1, v2, v3)

或者

t = f()                           # where t is the (v1, v2, v3)
result1, result2, result3 = t

实际上,Python 不允许像在其他语言中那样定义输出参数。你可以认为你正在传递参数对象的地址,如果传递的对象允许修改,你可以修改它。但是,例如,您永远无法为具有初始None值的传递参数获得新结果。您不能通过函数的输出参数分配 Python 变量——在 Python 中没有类似的机制。

从函数内部返回新创建的值(对象)的唯一自然而直接的方法是使用return命令。但是,Python 函数不会限制您可以返回多少个参数。(好吧,如果它是一个元组,则总是一个可以在以后分解为元素的元素。)

如果您想在调用者代码中测试实际返回的内容,您可以编写自己的函数,在返回以下值的情况下执行一些特殊操作:None, single,一定长度的元组 (len(t)可用于获取元素的数量在返回的元组中t)。您的函数还可以测试single每个元组元素的类型或类型并相应地工作。

于 2013-01-03T22:20:43.460 回答
4

我倾向于做的是让我的函数返回所有内容(作为元组的元素),然后只解压缩我需要的那些:

def my_func():
    # do stuff...
    return mean, stddev, otherstat, a, b

mu, sig, _, a, _ = myfunc()

在这里,我返回所有内容,但仅将第一个、第二个和第四个变量分配给我将在调用范围中使用的变量。该_变量是作为我不想要/不需要的变量的占位符的一次性使用。

于 2017-08-26T22:13:22.600 回答
3

在 Matlab 中,输出参数的数量实际上是函数的输入之一。在 Python 中情况并非如此,因此您已设置函数的接口以不同方式反映这一点。

例如,这是一个将 upper() 应用于一组字符串的函数,用户可以期望输入的数量等于输出的数量。语法也非常类似于 Matlab 的。

>>> def var_returns_f(*args):
...     return [str.upper() for str in args]
... 
>>> 
>>> a, b = var_returns_f('one', 'two')
>>> 
>>> a
'ONE'
>>> b
'TWO'
于 2015-06-22T09:45:59.227 回答
3

我有一个奇怪的想法...

def nargout():
   import traceback
   callInfo = traceback.extract_stack()
   callLine = str(callInfo[-3].line)
   split_equal = callLine.split('=')
   split_comma = split_equal[0].split(',')
   return len(split_comma)

def fun():
   this = nargout()
   if this == 1:
       return 3
   else:
       return 3, 4

a = fun()
a, b = fun()

我现在真的很想念 Matlab :D


通过以下方式改进:

def nargout(*args):
   import traceback
   callInfo = traceback.extract_stack()
   callLine = str(callInfo[-3].line)
   split_equal = callLine.split('=')
   split_comma = split_equal[0].split(',')
   num = len(split_comma)
   return args[0:num] if num > 1 else args[0]

def fun(nparray):
   return nargout(np.mean(nparray), np.std(nparray))

arr = np.array([3, 4, 5])
mean = fun(arr)
mean, std = fun(arr)
于 2018-12-13T20:49:10.617 回答