Python中的nargout

Nik*_*Nik 21 python multiple-variable-return

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()
Run Code Online (Sandbox Code Playgroud)

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

是否有Pythonic方式这样做?还是一个黑客的方式?

Bre*_*arn 19

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

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

这是作为Python哲学的"显性优于隐式"的示例.如果你想要两个参数,你必须明确地说你想要两个参数.在Python中不鼓励根据展望未来来看看将要对结果做些什么进行隐式决定.这是完全可能的,a = f(x)希望得到一个双元素元组.

像你这样的例子,有很多更好的方法.一个是做mean, std = a.mean(), a.std(),或者更普遍x, y = someFunc(a), otherFunc(a).如果通常需要这种特定的值组合,并且您不希望复制的两个操作共享一些昂贵的计算,那么创建一个可以清楚地返回两者并执行的第三个函数x, y = funcThatReturnsTwoThings(a).所有这些都是明确的方法,如果他们做不同的事情,保持功能分开.

  • Matlabs nargout不是魔法,也不是隐含的,Matlabs也不是[a,b] = f(x)`类似于Pythons`(a,b)= f(x)`.相反,Matlab中的语法`[a,b] = f(x)`导致Matlab告诉`f`"nargout = 2".它是Matlab语言中一个定义明确的语法规则,没有任何模糊的情况.这个Matlab功能很不寻常,不会出现在Python或我所知的任何其他语言中.但是,我不认为这是因为Python的Zen中的任何规则. (7认同)

pep*_*epr 9

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

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

如果没有return命令,None则函数体结束时函数返回.它就像你return在body return None的末尾或者body的末尾显式地没有参数一样.

如果您使用return None(None可以存储在变量中)或return没有参数,None则返回调用者.

如果您return single,该single对象将返回给调用者.

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

result1, result2, result3 = f()的情况下是另一种语法糖.该f()返回的元组和它的元素自动提取给定的变量.你实际上做了:

result1, result2, result3 = (v1, v2, v3)
Run Code Online (Sandbox Code Playgroud)

要么

t = f()                           # where t is the (v1, v2, v3)
result1, result2, result3 = t
Run Code Online (Sandbox Code Playgroud)

实际上,Python不允许像其他语言中那样定义输出参数.您可以考虑传递参数对象的地址,如果传递的对象允许修改,您可以修改它.但是,例如,你永远无法将新结果传递给最初具有None值的传递参数.你不能通过函数的输出参数来分配Python变量 - 没有像Python那样的机制.

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

如果你想在调用者代码来测试什么实际返回,您可以编写自己的函数,它的情况下,一些特别的东西在那里被送回以下值:None,single,一些长度的元组(len(t)可以用来获取元素的数量在返回的元组中t).您的函数还可以测试single每个元组元素的类型或相应的工作.


RBF*_*F06 5

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

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

mu, sig, _, a, _ = myfunc()
Run Code Online (Sandbox Code Playgroud)

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

  • 如果更多人偶然发现这一点:您还可以获取所需的值并将其余值解压到 **throaway tuple** 中,例如 `mu, *_ = myfunc()`。主要的兴趣是您不需要知道有多少无用的返回值被丢弃。 (2认同)

yip*_*iao 5

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

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()
Run Code Online (Sandbox Code Playgroud)

我现在真的很想念 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)
Run Code Online (Sandbox Code Playgroud)