Pasar valores por referencia en programación multihilo
Frecuentes
Visto 589 veces
0
Escribí un programa que usa el módulo de subprocesos para crear un subproceso que agrega 1 a una variable previamente definida, pero, una vez que finaliza el programa, el valor de la variable sigue siendo el mismo. He intentado esto:
from threading import Thread
def plus_one(var):
return var + 1
var = 0
print var
my_adder = Thread(target = plus_one, args = (var, ))
var = my_adder.start()
my_adder.join()
print var
Pero no funciona... ¿qué debo hacer? Ya he buscado algo de información pero todo es bastante confuso..!
3 Respuestas
1
Python "variables"
En python, no tiene 'variables' y no puede 'pasar por referencia' o 'pasar por valor'. Tiene 'nombres', que se vinculan a valores en la memoria. Esos valores pueden cambiar, o el nombre puede cambiar. Por ejemplo:
>>> x = 21
>>> y = x
>>> y
21
>>> x = 100
>>> y
21
Cuando crea una función, cualquier nombre cuyo valor cambie se trata como un nombre nuevo y no apunta al exterior:
>>> x = 21
>>> def do(a):
x = a + 100 # x here is a new local name, since you've assigned to it.
>>> do(x)
>>> x
21
Sin embargo, si todo lo que haces es lectura el nombre, entonces python le dejará acceso para leer la variable desde el 'alcance' principal:
>>> x = 21
>>> def p():
print (x)
>>> p()
21
Este es el primer problema con su código. La forma de hacerlo es usar un nombre que se define globalmente y decirle a la función que use ese nombre global:
>>> x = 21
>>> def do():
global x
x = 41
>>> do()
>>> x
41
(En python 3, puede usar nonlocal
más bien que global
para acceder a un nombre no global desde un ámbito principal).
Cuando estaba devolviendo un valor, debe asignar el nombre a ese valor en el mismo ámbito en el que está definido.
Nombres mutables e inmutables:
Si vincula un nombre a algo como un número, una tupla o una cadena, entonces el valor es immutable
. No puedes cambiarlo. Así que cada vez que dices x = 1
y luego x = 21
, no está cambiando el valor de x, está volviendo a vincular x para que apunte a un nuevo valor. es por eso que el y = x
ejemplo y no cambió. Todavía estaba vinculado al valor anterior. El valor no cambió, pero x
ahora señaló a uno nuevo.
Sin embargo, no todas las cosas en Python son inmutables. Las listas, dictados, objetos, etc., no son inmutables. Entonces:
>>> x = [100]
>>> def do(l):
l[0] = 50
>>> do(x)
>>> x
[50]
También:
>>> x = [21]
>>> y = x
>>> x[0] = 50
>>> y
[50]
Esto se puede usar para 'pasar valores por referencia', si realmente lo necesita. Sin embargo, si está abusando de él, generalmente es una buena señal de que, de alguna manera, la estructura del código es incorrecta.
Hilos y acceso variable
Lo que estabas haciendo era devolver un nuevo valor, pero no asignarlo a ningún lado. La amenaza .start()
método no funciona de esa manera. La razón es que si lo hiciera, estaría bloqueando el subproceso actual (que en realidad vincula el nombre al nuevo valor) esperando que el que devuelve el nuevo valor lo configure, lo que preferiría perder el punto de los subprocesos. .
Puede usar los métodos anteriores para evitar esto.
Una cosa que realmente debe tener en cuenta es que las variables a las que se accede desde varios subprocesos pueden dar bastante miedo, ya que las cosas no se comportan del todo bien, si varios subprocesos intentan acceder a los mismos valores al mismo tiempo.
Aquí hay un muy buen artículo sobre 'bloqueos' y cómo estar seguro trabajando con hilos.
http://effbot.org/zone/thread-synchronization.htm
¡Que la disfrutes!
Respondido el 30 de enero de 14 a las 03:01
1
Python pasa solo objetos por referencia, los valores escalares se pasan por valores. SO, si defines una clase
class IntWrapper(object):
val = 1
def incr(obj)
obj.val += 1
Que funcionará
Respondido el 03 de diciembre de 13 a las 13:12
0
para eso debes inicializar tu variable como 0
en el momento de la declaración también cambie su nombre de variable
porque var es una palabra clave en sí misma, por lo que es bueno usar otra variable
Respondido el 03 de diciembre de 13 a las 13:12
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas python multithreading pass-by-reference or haz tu propia pregunta.
Si varios subprocesos incrementarán el mismo contador, debe estar protegido por un candado. - Janne Karila