Python - Objeto itertools.combinations() modifica mis variables de entrada y salida, aún despues de ejecutars

 
Vista:
sin imagen de perfil

Objeto itertools.combinations() modifica mis variables de entrada y salida, aún despues de ejecutars

Publicado por Osvaldo (3 intervenciones) el 25/05/2018 08:35:18
Hola!

Estoy trabajando con un código que genera combinaciones sin repetición. Para esto uso el método res=itertools.combinations(Ent1,Ent2). Este modo me genera un objeto con todas las combinaciones. El problema es que, cuando yo opero con los elementos de res, se modifican todas las variables que estén involucradas en la función, lo cual, según yo, no debería pasar.

Para explicarme correctamente pongo el código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import itertools
N = 3;  numE = 3
opc = [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
 
res = itertools.combinations(opc, numE)
 
for e in res:
    print (e)
    ee = e #*
    print (ee)#*
    print ('    iterando    ')#*
    for i in range(len(ee)):#*
        ee[i][0] = ee[i][0] * 2#*
        ee[i][1] = ee[i][1] * 3#*
    print (e)#*
    print (ee,'\n\n')#*
 
print ('Salí del ciclo')
print ('Opc= ',opc)


Ahora, si dentro del ciclo, yo comento todo excepto el print(e) (todo lo que tiene #*), el código funciona de maravilla, y me devuelve lo que debería de volver (los valores de "e" correctos).

Ahora, lo que me interesa es operar con los elementos de "e". Para esto, creo un duplicado, "ee=e". Lo que yo quiero es modificar los elementos de "ee", sin tocar los de "e". Según yo, eso no debería ser ningún problema.
Pero resulta que, cuando yo modifico "ee", automáticamente se modifica también "e", lo que me descompone todo el ciclo, y las combinaciones ya no son las que deberían ser. Más extraño aún, cuando yo modifico a "ee", también se modifica la variable de entrada opc.

Según yo, esto no tiene senido, modificar "ee", no debería alterar a "e" y menos "opc". ¿Es normal que esto pase? ¿Es debido a la construcción de itertools, o se trata de algún bug? ¿o es algún error tonto que estoy cometiendo?


PD. Trabajo en Ubuntu, en anaconda 3-5.1.0 que interpreta con python 3.6

PD2: Ya encontré el problema, "e" es una tupla, y debería ser inmutable. El detalle es que es una tupla rellena de listas. Python sí me permite modificar las listas dentro de una tupla pero, al parecer, si esa tupla es la "copia" de otra, todas las tuplas se modifican.
Ahora, ¿eso cuenta como bug, no?

Finalmente, tenganme paciencia, es mi primera vez en el foro, así que hago ésta aclaración en lo que encuentro como borrar el hilo...
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

Objeto itertools.combinations() modifica mis variables de entrada y salida, aún despues de ejecutars

Publicado por Osvaldo (3 intervenciones) el 25/05/2018 10:29:12
Aclarando lo que encontré, mi observacion fue la siguiente:

Si yo tengo una lista con listas, puedo copiarla en otra variable, y operar sin problema.

Si yo tengo una tupla de listas, y la copio a una segunda variable; y luego modifico un valorer en esa segunda variable, la tupla original también se modifica.
Esto pasó siempre. Intenté castear la tupla a una lista; Intenté hacer una lista con los elementos en el ciclo, y luego operar; intente acceder a cada elemento individual de la tupla para luego armar una nueva lista.
El resultado siempre fue el mismo, si yo modifico la segunda variable, se modifica también la primera:

Ejm:
1
2
3
4
5
6
tupla = ([1,2],[3,4],[5,6])
lista = list(tupla)
lista[1][1] = 10
 
print (tupla)
print (lista)

Si ingresan ese código, podrán observar que tanto la lista como la tupla se modifican. Según yo, eso no debería pasar, si modifico la lista, la tupla no se debería modificar.

Tal vez soy muy nuevo en esto de la programación, pero no le veo sentido a esto. ¿Se tratará de un bug? ¿o es normal que pase eso?

Se supone que la tupla es inmutable, por eso la cópio en una lista, pero al modificar esa lista, no se debería modificar la tupla original...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de kip
Val: 1.120
Bronce
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Objeto itertools.combinations() modifica mis variables de entrada y salida, aún despues de ejecutars

Publicado por kip (257 intervenciones) el 25/05/2018 19:17:18
Hola, voy a explicarte el porque te sucede esto:

Python opera de una manera muy diferente a como uno cree y como se suele hacerse en otros lenguajes de programación, tiene mucha optimizacion detras sobre todos los objetos(en Python todo es un objeto) tratando a las variables como simples "etiquetas" que apuntan a estos, para entenderlo mejor mira esto:

1
2
3
4
>>> a = 123
>>> b = 123
>>> id(a) == id(b)
True

Pero que es ese numero que retorna id ? Pues simple, es un identificador unico del objeto en memoria y como puedes ver ambas variables apuntan al mismo objeto, incluso siendo un simple entero.

En el anterior ejemplo no tenemos problema, puesto que si cambiamos el valor de b sumandole un numero o restandole otro, el identificador cambia porque se crea otro objeto con este valor:

1
2
3
4
5
6
7
8
9
10
11
>>> a = 123
>>> b = 123
>>> id(a) == id(b)
True
>>> b += 1
>>> id(a) == id(b)
False
>>> id(b)
17862445440
>>> id(a)
17862445408

Pero entonces que sucede con los otros objetos, como los tipos de estructuras de dato que solemos usar siempre ?
Pues sucede lo que te pasa con tu codigo, al apuntar al mismo objeto en memoria los cambios que hagas se reflejan en todas las variables que esten relacionadas con este objeto.

Que podemos hacer para que no suceda esto ?
Pues bien, lo mejor es hacer un 'deep copy' usando el modulo copy, asi:

1
2
3
4
5
6
7
8
>>> from copy import deepcopy
>>> a = [[1, 2], [3, 4]]
>>> b = deepcopy(a)
>>> a[0] = ['a', 'b']
>>> a
[['a', 'b'], [3, 4]]
>>> b
[[1, 2], [3, 4]]

Te dejo entonces dos links por si quieres indagar mas sobre este tema, yo trate de resumirlo para que lo entiendas mejor.
http://cryptroix.com/2016/10/23/everything-object-python/
https://realpython.com/copying-python-objects/
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
sin imagen de perfil

Objeto itertools.combinations() modifica mis variables de entrada y salida, aún despues de ejecutars

Publicado por Osvaldo (3 intervenciones) el 26/05/2018 08:01:18
Me ha quedado claro, muchas gracias!!

Y usar deepcopy me ha resuelto el problema. Operar de esa forma era necesario para optimizar mi código. Ahora que decidí involucrarme con más seriedad en la programación, saber este tipo de detalles creo que es fundamental !!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar