Problema de encapsulado con python

Consulte acerca de programas, técnicas, algoritmos etc.

Problema de encapsulado con python

Notapor hechelion » Dom Mar 04, 2012 7:39 pm

Saludos, voy a ver si ahora tengo más suerte con alguna respuesta, ya que acá hay más gente que use python.

Tengo un problema muy extraño con python, creé una clase y dentro de la clase una lista (yo espero que la lista sea local a la clase y por ende, tener una lista por cada objeto creado)

El problema viene, por que estoy creando objetos de forma dinámica en tiempo de ejecución según sean los dato que leo de un archivo y los agrego a un diccionario. El problema, es que cuando agrego los datos a la lista interna de cada objeto, es como si esa lista fuese una sola variable global para todos los objetos, en vez de ser una variable única e independiente para cada objeto.

Tengo un archivo de texto donde almaceno unos datos:

Código: Seleccionar todo
cabecera
linea_1 ;;;;;ID_0;;;;;;;;;
linea_2 ;;;;;ID_1;;;;;;;;;
linea_3 ;;;;;ID_0;;;;;;;;;
linea_4 ;;;;;ID_2;;;;;;;;;
linea_5 ;;;;;ID_1;;;;;;;;;


Creé el siguiente programa en python, para agrupar los datos (o lineas) según sea el ID.
Código: Seleccionar todo
import struct
import sys
import glob
import os
import types
import binascii
import re

class ClsPJ:
    #Clase para almacenar los datos de cada PJ
    cadena = []   
    nombre = ""
   
    def __init__(self):
        pass
   
    def AddDato(self, dato):
        self.cadena.append(dato)
   
    def printDato(self):
        for linea in self.cadena:
            print(linea)


def leerArchivo(ruta):
    #Desglosa un archivo de log
    log = open(ruta,'r')
    for linea in log.readlines()[1:]: #Recorrermos el log, menos la primera l?nea que es la cabecera
        campos = linea.split(";") #cortamos la linea en sus respectivos campos
        if not campos[5] in lstPJ: #Si la key no existe en el diccionario
            lstPJ[campos[5]] = ClsPJ() #Creamos una entrada nueva en el diccionario
            lstPJ[campos[5]].nombre = campos[5] #escribimos la key en el objeto
        lstPJ[campos[5]].AddDato(linea) #agregamos el dato al objeto


lstPJ = {} #creamos el diccionario que contendr? los datos
leerArchivo("output.txt") #Leemos el archivo de prueba

for k, v in lstPJ.iteritems(): #imprimimos los datos para probar
    print(v.nombre)
    v.printDato()


El problema lo tengo al momento de agregar el dato a cada objeto, yo espero que la línea
" lstPJ[campos[5]].AddDato(linea) #agregamos el dato al objeto" agregue una línea a un objeto y esperaría la siguiente salida de mi programa (cada línea estaría agrupada):

Código: Seleccionar todo
ID_0
linea_1 ;;;;;ID_0;;;;;;;;;
linea_3 ;;;;;ID_0;;;;;;;;;

ID_1
linea_2 ;;;;;ID_1;;;;;;;;;
linea_5 ;;;;;ID_1;;;;;;;;;

ID_2
linea_4 ;;;;;ID_2;;;;;;;;;



Sin embargo, la salida actual de mi programa es la siguiente:

Código: Seleccionar todo
ID_0
linea_1 ;;;;;ID_0;;;;;;;;;
linea_2 ;;;;;ID_1;;;;;;;;;
linea_3 ;;;;;ID_0;;;;;;;;;
linea_4 ;;;;;ID_2;;;;;;;;;
linea_5 ;;;;;ID_1;;;;;;;;;

ID_1
linea_1 ;;;;;ID_0;;;;;;;;;
linea_2 ;;;;;ID_1;;;;;;;;;
linea_3 ;;;;;ID_0;;;;;;;;;
linea_4 ;;;;;ID_2;;;;;;;;;
linea_5 ;;;;;ID_1;;;;;;;;;

ID_2
linea_1 ;;;;;ID_0;;;;;;;;;
linea_2 ;;;;;ID_1;;;;;;;;;
linea_3 ;;;;;ID_0;;;;;;;;;
linea_4 ;;;;;ID_2;;;;;;;;;
linea_5 ;;;;;ID_1;;;;;;;;;



Como ven, por algún extraño motivo que no he logrado comprender, me crea bien los 3 objetos dentro del diccionario, pero a cada objeto le está agregando las 5 líneas en vez de agregar solo la línea que corresponde.


Por lo que entiendo, luego de hacer un montón de pruebas, es como si la variable "cadena" no fuera local y única a cada objeto, si no, que fuera una única variable global y todos los objetos apuntan a la misma lista.
No me cuadra, como puede pasar eso, si "cadena" fue definida dentro de la clase (el programa es todo lo que hay ahí). En especial, si la propiedad "nombre" funciona bien, por lo cual sé que tengo 3 objetos diferentes, pero desconozco por que tengo solo una lista global en vez de tener 3 listas independientes.
¿Alguna idea?
Avatar de Usuario
hechelion
 
Mensajes: 29
Registrado: Vie Ene 13, 2012 3:06 pm
Ubicación: Houston

Re: Problema de encapsulado con python

Notapor hechelion » Dom Mar 04, 2012 8:10 pm

Luego de una buena lucha, se me ocurrió probar algo que funciona.
moví la creación de las variables al método __init__ de esa forma pude anteponer el "self" antes de "definir" las propiedades y ahora está funcionando bien (una lista por objeto). Pero sigo con la duda de por que fallaba de la otra forma.

Código: Seleccionar todo
    def __init__(self):
        self.cadena = []
        self.nombre = ""


Mis disculpas por postear seguido, pero hasta hace unos minutos no lograba encontrar ninguna solución (luego de dos días tratando de resolverlo) y de pronto se me ocurrió probar esa opción. Por cierto, si alguien sabe por qué no funciona la forma anterior, le agradecería si me lo explica.
Avatar de Usuario
hechelion
 
Mensajes: 29
Registrado: Vie Ene 13, 2012 3:06 pm
Ubicación: Houston

Re: Problema de encapsulado con python

Notapor Mightygaver » Dom Mar 04, 2012 10:53 pm

Hola Hechelion,

El motivo principal por el que no te funcionaba la primera solución, es que estabas declarando las variables en un espacio común para todas las instancias de la clase.

No sé si estarás familiarizado con Java, C++ o PHP. Todos estos lenguajes también permiten utilizar variables compartidas para todas las instancias de una misma clase, pero la diferencia principal es que en ellos se ha de poner la palabra clave static con lo que queda más claro que no son variables para cada instancia. Las variables que utilizaste en la primera solución eran de este tipo.

En cambio, la segunda solución es la manera correcta, utilizando self para agregar dinámicamente los campos que quieras poner al objeto al que self hace referencia.

Espero haberlo explicado correctamente, aunque no se me ocurre ninguna manera diferente de explicar los miembros estáticos sin hacer analogía de otros lenguajes, ya que personalmente nunca entendí porqué se llaman static :shock:
Mightygaver
 
Mensajes: 69
Registrado: Vie Ago 27, 2010 5:46 pm
Ubicación: Vila-real, España

Re: Problema de encapsulado con python

Notapor hechelion » Dom Mar 04, 2012 11:51 pm

Quedo muy agradecido Mightygaver.

Con la explicación que me diste me quedó perfectamente claro, la verdad, nunca se me ocurrió pensar que el problema venía por ese lado, en especial por que no se usa ninguna palabra reservada ni nada que te haga tomar conciencia de la diferencia de comportamiento.

Sobre static, yo tengo entendido que es porque la variable se mantiene estática en la memoria y puede ser accedida independiente del lugar donde se cargue la instancia al objeto.
Avatar de Usuario
hechelion
 
Mensajes: 29
Registrado: Vie Ene 13, 2012 3:06 pm
Ubicación: Houston


Volver a General

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado