two tuple for def array python multiple-variable-return

python - tuple - nargout en pitón



tuple python (5)

En Matlab, el número de argumentos de salida es en realidad una de las entradas a una función. Este no es el caso en Python y, por lo tanto, ha configurado la interfaz de la función para reflejar esto de manera diferente.

Por ejemplo, aquí hay una función que aplica upper () a un grupo de cadenas, y el usuario puede esperar que el número de entradas sea igual al número de salidas. La sintaxis también es muy similar a la de Matlab.

>>> def var_returns_f(*args): ... return [str.upper() for str in args] ... >>> >>> a, b = var_returns_f(''one'', ''two'') >>> >>> a ''ONE'' >>> b ''TWO''

¿Python tiene algún equivalente de nargout en MATLAB? Considero que este enfoque es muy claro si queremos mantener la cantidad de parámetros de retorno flexibles. ¿Hay alguna manera de averiguar cuántos parámetros de salida se han solicitado? Algo así como el siguiente código de pseudo-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()

Entonces, si llamo a esta función como mean = var_returns_func(someNumPyarray) , debería devolver un solo valor. Pero si lo llamo mean,std = var_returns_func(someNumPyarray) , debería devolver 2 valores.

¿Hay una forma pitónica de hacer esto? ¿O una forma de hacky?


La función no puede saber qué se va a hacer con el valor de retorno, por lo que no puede saber cuántas se necesitan. Lo que podría hacer es pasar nargout como un argumento a su función y usarlo para decidir qué devolver:

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

Este es un ejemplo de "explícito es mejor que implícito" como filosofía de Python. Si quiere eliminar dos argumentos, debe decir explícitamente que quiere eliminar dos argumentos. La decisión implícita basada en mirar hacia el futuro para ver qué se va a hacer con el resultado no se recomienda en Python. Es perfectamente posible hacer a = f(x) y querer obtener una tupla de dos elementos en a.

Para ejemplos como el tuyo, hay muchas formas mejores. Una es simplemente mean, std = a.mean(), a.std() , o más generalmente x, y = someFunc(a), otherFunc(a) . Si esta combinación particular de valores es comúnmente necesaria, y hay un cálculo costoso compartido por ambas operaciones que no quiere duplicar, haga una tercera función que claramente devuelva ambas y haga x, y = funcThatReturnsTwoThings(a) . Todas estas son formas explícitas de mantener las funciones separadas si hacen cosas diferentes.


Lo que tiendo a hacer es que mi función devuelva todo (como elementos de una tupla), luego solo desempaquetar los que necesito:

def my_func(): # do stuff... return mean, stddev, otherstat, a, b mu, sig, _, a, _ = myfunc()

Aquí estoy devolviendo todo, pero solo asignando las variables 1ª y 4ª a las variables que usaré en el alcance de la llamada. La variable _ es un objeto desechable que actúa como un marcador de posición para las variables que no quiero / necesito.


No puedo hablar por nargout en MATLAB ya que no lo sé y no puedo imaginar cómo debería usarse correctamente. Sin embargo, es posible que desee cambiar la vista a lo que realmente hace una función (o método) de Python).

En realidad, Python siempre devuelve exactamente un valor. O es Ninguno, o es un valor único de algún tipo específico, o es un objeto único del tipo de tuple .

Si no hay un comando de return , la función devuelve None si el cuerpo de la función termina. Es lo mismo que si escribiera explícitamente return sin argumentos al final del cuerpo, o return None al final del cuerpo.

Si usa el return None (el None se puede almacenar en una variable) o el return sin argumentos, el None se devuelve a la persona que llama.

Si return single , el single objeto vuelve a la persona que llama.

Si return v1, v2, v3 , en realidad devuelve una tupla (v1, v2, v3) . Es solo un azúcar sintáctico que no necesitas escribir los paréntesis.

El result1, result2, result3 = f() en el caso es solo otro azúcar sintáctico. La f() devuelve la tupla y sus elementos se extraen automáticamente a las variables dadas. Usted realmente hace:

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

o

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

En realidad, Python no permite definir argumentos de salida como es habitual en otros idiomas. Puede pensar en términos de que está pasando direcciones de los objetos de argumento y si el objeto pasado permite ser modificado, puede modificarlo. Pero nunca puede obtener un nuevo resultado para un argumento pasado que inicialmente None tenía valor, por ejemplo. No puede asignar una variable de Python a través del argumento de salida de la función, no hay un mecanismo como el de Python.

La única forma natural y directa de devolver los valores (objetos) recién creados desde dentro de la función es usar el comando de return . Sin embargo, una función de Python no limita la cantidad de argumentos que se pueden devolver. (Bueno, siempre uno solo que luego se puede dividir en elementos si se tratara de una tupla).

Si desea probar en el código de la persona que llama lo que realmente se devolvió, puede escribir su propia función que haga algo especial en los casos en que se devolvieron los siguientes valores: None , single , se puede usar una tupla de cierta longitud ( len(t) para obtener el número de elementos en la tupla devuelta t ). Su función también puede probar el tipo de elemento single o de cada uno de los elementos de la tupla y trabajar en consecuencia.


Tengo una idea extraña ...

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()

Realmente extraño a Matlab ahora: D

Mejorado por:

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)