Pasar valores por referencia en programación multihilo

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..!

preguntado el 03 de diciembre de 13 a las 13:12

3 Respuestas

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

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

Si varios subprocesos incrementarán el mismo contador, debe estar protegido por un candado. - Janne Karila

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

var no es palabra clave en Python - volcán

@volcano sí, pero es un function - K DawG

----> 1 var NameError: el nombre 'var' no está definido - volcán

@volcano ups lo confundió con vars - K DawG

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.