Modificación de los argumentos de la función.

Lo siento si esta es una pregunta tonta, pero he buscado por un tiempo y no he encontrado la respuesta.

Si estoy escribiendo una función python, por ejemplo:

def function(in1, in2): in1=in1+1 in2=in2+1 

¿Cómo puedo hacer que estos cambios se mantengan?

Sé por qué no, esto se ha abordado en muchas respuestas, pero no pude encontrar una respuesta a la pregunta de cómo hacer que realmente lo hagan. Sin devolver valores o hacer algún tipo de clase, ¿realmente no hay manera de que una función opere sus argumentos en un sentido global?

También quiero que estas variables no sean globales en sí mismas, ya que quiero poder hacer esto:

 a=1 b=2 c=3 d=4 function(a,b) function(c,d) 

¿Esto es sólo una ilusión?

Se puede hacer, pero te lo advierto: ¡ no será bonito ! Lo que puede hacer es capturar el marco de la persona que llama en su función, luego recoger la línea de llamada, analizarla y extraer los argumentos pasados, luego compararlos con su firma de función y crear un mapa de argumentos, luego llamar a su función y una vez que su función termina compara los cambios en la stack local y actualiza el marco del llamante con los cambios asignados. Si quieres ver lo tonto que puede ser, aquí tienes una demostración:

 # HERE BE DRAGONS # No, really, here be dragons, this is strictly for demonstration purposes!!! # Whenever you use this in code a sweet little pixie is brutally killed! import ast import inspect import sys def here_be_dragons(funct): # create a decorator so we can, hm, enhance 'any' function def wrapper(*args, **kwargs): caller = inspect.getouterframes(inspect.currentframe())[1] # pick up the caller parsed = ast.parse(caller[4][0], mode="single") # parse the calling line arg_map = {} # a map for our tracked args to establish global <=> local link for node in ast.walk(parsed): # traverse the parsed code... # and look for a call to our wrapped function if isinstance(node, ast.Call) and node.func.id == funct.__name__: # loop through all positional arguments of the wrapped function for pos, var in enumerate(funct.func_code.co_varnames): try: # and try to find them in the captured call if isinstance(node.args[pos], ast.Name): # named argument! arg_map[var] = node.args[pos].id # add to our map except IndexError: break # no more passed arguments break # no need for further walking through the ast tree def trace(frame, evt, arg): # a function to capture the wrapped locals if evt == "return": # we're only interested in our function return for arg in arg_map: # time to update our caller frame caller[0].f_locals[arg_map[arg]] = frame.f_locals.get(arg, None) profile = sys.getprofile() # in case something else is doing profiling sys.setprofile(trace) # turn on profiling of the wrapped function try: return funct(*args, **kwargs) finally: sys.setprofile(profile) # reset our profiling return wrapper 

Y ahora puede decorar fácilmente su función para que pueda realizar esta parodia impía:

 # Zap, there goes a pixie... Poor, poor, pixie. It will be missed. @here_be_dragons def your_function(in1, in2): in1 = in1 + 1 in2 = in2 + 1 

Y ahora, demostración:

 a = 1 b = 2 c = 3 d = 4 # Now is the time to play and sing along: Queen - A Kind Of Magic... your_function(a, b) # bam, two pixies down... don't you have mercy? your_function(c, d) # now you're turning into a serial pixie killer... print(a, b, c, d) # Woooo! You made it! At the expense of only three pixie lives. Savage! # prints: (2, 3, 4, 5) 

Esto, obviamente, funciona solo para funciones no anidadas con argumentos posicionales, y solo si pasa argumentos locales simples, no dude en pasar por el agujero de conejo de manejar argumentos de palabras clave, stacks diferentes, llamadas devueltas / envueltas / encadenadas y otros chanchullos si eso es lo que te apetece

O bien, puede usar estructuras inventadas para esto, como globales, clases o incluso objetos mutables encerrados. Y deja de asesinar duendecillos.

Si desea modificar el valor de las variables, puede solicitar que su código sea

 def func(a,b): int1 = a + 2 int2 = b + 3 return int1,int2 a = 2 b = 3 a,b = func(a,b) 

Esto le permite realmente cambiar los valores de las variables a y b con la función.

tu puedes hacer:

 def function(in1, in2): return in1 + 1 , in2 + 1 a, b = function(a,b) c, d = function(c,d) 

Las funciones de Python están cerradas -> cuando se llama a la función (a, b), a y b se reasignan a referencias / punteros locales (a la función) in1 e in2, que no son accesibles fuera de la función. proporcione referencias a esos nuevos valores sin utilizar las variables globales, tendrá que pasar eso de vuelta a través de la devolución.

Cuando pasa una matriz o un objeto no primitivo a una función, puede modificar los atributos del objeto y hacer que esas modificaciones sean visibles a otras referencias para ese objeto externo, porque el objeto en sí contiene los punteros a esos valores, haciendo que lo visible sea cualquier otra cosa. sosteniendo un puntero a ese objeto.