Foros del Web » Programando para Internet » Python »

Objeto miembro de una lista.

Estas en el tema de Objeto miembro de una lista. en el foro de Python en Foros del Web. Buen día a todos. Tengo un problema con un código en python 3. Me explico. Tengo una clase: Código: class LRItem(object): def __init__(self): self.rule = ...
  #1 (permalink)  
Antiguo 11/03/2014, 16:24
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Objeto miembro de una lista.

Buen día a todos.

Tengo un problema con un código en python 3.
Me explico.

Tengo una clase:
Código:
class LRItem(object):

    def __init__(self):
        self.rule = None
        self.dot = 0
        self.lookAhead = ''

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    def show(self):
        if self.rule is None:
            print("Empty LR(1) item")
        text = self.rule.leftHand.text
        text += " -> "
        for tokens in self.rule.rightHands[:self.dot]:
            text += ' ' + tokens.text
        text += ' .'
        for tokens in self.rule.rightHands[self.dot:]:
            text += ' ' + tokens.text

        text += ' ||' + self.lookAhead
        print(text)
Como se puede observar, uso __eq__ para hacer comparaciones de igualdad. No se que tan correcto sea esto.

Dentro de una función tengo una lista donde voy agregando objetos de la clase especificada.
El problema es que llega un momento en que hago lo siguiente:
Código:
itemsList = []
.
.
for la in lookAheads:
    newItem.lookAhead = la
    if newItem not in itemsList:
        itemsList.append(newItem)
.
.
lookAheads es una lista de strings.
Por cada objeto string en la lista cambio mi objeto tipo LRItem, es decir, newItem.
Después intento agregar ese nuevo item a mi lista de objetos.

Lo curioso es que aunque noItem.lookAhead contenga un valor diferente, ya no me agrega el nuevo item a la lista. Parece ser que la condución
Código:
newItem not in itemsList:
falla de alguna manera.

Alguien me podría explicar que sucede? O que estor haciendo mal?
Por que el operador in no esta dando el resultado correcto??

Saludos
  #2 (permalink)  
Antiguo 11/03/2014, 16:48
 
Fecha de Ingreso: enero-2012
Ubicación: Buenos Aires
Mensajes: 745
Antigüedad: 12 años, 3 meses
Puntos: 35
Respuesta: Objeto miembro de una lista.

Si en itemsList tenés instancias de LRItem, no debería ser:

Código Python:
Ver original
  1. if newItem.lookAhead not in itemsList:

Ademas, que tendria que ver __eq__ en todo esto?

  #3 (permalink)  
Antiguo 11/03/2014, 23:19
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Respuesta: Objeto miembro de una lista.

Cita:
Iniciado por carbon Ver Mensaje
Si en itemsList tenés instancias de LRItem, no debería ser:

Código Python:
Ver original
  1. if newItem.lookAhead not in itemsList:

Ademas, que tendria que ver __eq__ en todo esto?

Perdón. No comprendí tu respuesta.

itemList es una lista de instancias de LRItem.
newItem.lookAhead es solo un string.

No comprendo cual es el punto de:

Código:
if newItem.lookAhead not in itemsList:
Saludos
  #4 (permalink)  
Antiguo 12/03/2014, 06:19
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: Objeto miembro de una lista.

Creo que estas reciclando el mismo objeto,

Que tal cambiar a:
Código Python:
Ver original
  1. for la in lookAheads:
  2.     newItem = LRItem()    # un objeto nuevo cada vez?
  3.     newItem.lookAhead = la
__________________
Visita mi perfil en LinkedIn
  #5 (permalink)  
Antiguo 12/03/2014, 09:39
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Respuesta: Objeto miembro de una lista.

Cita:
Iniciado por CalgaryCorpus Ver Mensaje
Creo que estas reciclando el mismo objeto,

Que tal cambiar a:
Código Python:
Ver original
  1. for la in lookAheads:
  2.     newItem = LRItem()    # un objeto nuevo cada vez?
  3.     newItem.lookAhead = la

Si. al parecer esa es la explicación.

No lo puse dentro del código. Lo que pasa es que busco que los demás campos sean los mismos. Solo cambio el lookAhead.
Supongo que tendre que hacer un nuevo objeto y copiar todos los campos.

No se si sea la manera más elegante..

Por cierto carbon, no soy un experto, pero pensé que el operador in usaba el __eq__ para buscar dentro de la lista. Corrigeme si estoy equivocado.

Saludos
  #6 (permalink)  
Antiguo 12/03/2014, 15:40
 
Fecha de Ingreso: enero-2012
Ubicación: Buenos Aires
Mensajes: 745
Antigüedad: 12 años, 3 meses
Puntos: 35
Respuesta: Objeto miembro de una lista.

Claramente yo tampoco, me equivoqué yo, disculpa!
  #7 (permalink)  
Antiguo 13/03/2014, 19:22
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 1 mes
Puntos: 1360
Respuesta: Objeto miembro de una lista.

Bueno chavo, por favor trata de darnos un código que podamos correr porque esta difícil andar adivinando de donde sale looksAhead, newItem u otras variables que vayan saliendo.

Si estas reusando el objeto newItem, obviamente vas a tener problemas porque, tu objeto es mutable y ademas siempre es una referencia al mismo objeto.

Asumi que estabas haciendo esto
Código Python:
Ver original
  1. class LRItem(object):
  2.  
  3.     def __init__(self):
  4.         self.rule = None
  5.         self.dot = 0
  6.         self.lookAhead = ''
  7.  
  8.     def __eq__(self, other):
  9.         return self.__dict__ == other.__dict__
  10.  
  11.     def __str__(self):
  12.         return self.lookAhead
  13.  
  14.     def __repr__(self):
  15.         return '"%s"' % self.__str__()
  16.  
  17.  
  18. lookAheads = ['a', 'b', 'c', 'd', 'a', 'd', 'c']
  19. itemsList = []
  20. newItem = LRItem()
  21. for la in lookAheads:
  22.     newItem.lookAhead = la
  23.     if newItem not in itemsList:
  24.         itemsList.append(newItem)
  25. print(itemsList)

Cuando tu querias:
Código Python:
Ver original
  1. class LRItem(object):
  2.  
  3.     def __init__(self):
  4.         self.rule = None
  5.         self.dot = 0
  6.         self.lookAhead = ''
  7.  
  8.     def __eq__(self, other):
  9.         return self.__dict__ == other.__dict__
  10.  
  11.     def __str__(self):
  12.         return self.lookAhead
  13.  
  14.     def __repr__(self):
  15.         return '"%s"' % self.__str__()
  16.  
  17.  
  18. lookAheads = ['a', 'b', 'c', 'd', 'a', 'd', 'c']
  19. itemsList = []
  20. for la in lookAheads:
  21.     newItem = LRItem()
  22.     newItem.lookAhead = la
  23.     if newItem not in itemsList:
  24.         itemsList.append(newItem)
  25. print(itemsList)

Para la construcción de una clase sencilla como la que tienes al menos deberías de plantearte los siguientes puntos: ¿Es mutable o inmutable el objeto? Definir algún tipo de ID o ID compuesto (Que atributos harán a este objeto único). Saber al menos de referencias a objetos. Trata de trabajar con métodos como __str__ en lugar de métodos como show.
  #8 (permalink)  
Antiguo 13/03/2014, 21:47
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Respuesta: Objeto miembro de una lista.

Hola razpeitia. Gracias por tu respuesta.

Tienes razón, no puse el suficiente código.

Lo que pasa, es que es un poco mas complicado.

Aunque lo qu tu pusiste es un buen reusmen de lo que necesito hacer:

Código:
for nt in grammar:
            if nt.leftHand == currentNT:
                newItem = LRItem()
                newItem.rule = nt
                newItem.dot = 0
                newItem.lookAhead = lrItem.lookAhead
                newItem.show()
                lookAheads = getLookAheads(grammar, newItem)
               
                for la in lookAheads:
                    newItem.lookAhead = la

                    if newItem not in itemsList:
                        itemsList.append(newItem)
Sin embargo, sustituyendo newItem.lookAhead = la por:
Código:
 tempItem = LRItem()
                    tempItem.rule = newItem.rule
                    tempItem.dot = newItem.dot
                    tempItem.lookAhead = la
funciona de manera correcta.

Todavía me confunde la manera en que python maneja algunas cosas, como el caso de los objetos mutables y no mutables.
Me surge una duda aqui.

Si tengo 2 objetos que fueron creados, pero con el mismo contenido. ¿Cómo los toma el operador in?

Código:
class Foo(object):
    def __init__(self):
        self.data=0

objA = Foo()
objA.data = 1

objB = Foo()
objB.data = 1

mylist = [objA]
Como se evaluaría

Código:
objB in mylist
Supongo que daría falso porque son objetos diferentes apesar de que el contenido es el mismo.

Alguien que me despeje esta duda?
Como lo haría para que esa condicion evalue verdadero?

SAludos
  #9 (permalink)  
Antiguo 13/03/2014, 23:26
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 1 mes
Puntos: 1360
Respuesta: Objeto miembro de una lista.

Efectivamente evaluaría falso el código que pusiste. Y es que por default checa con el operador is.

Código Python:
Ver original
  1. class Foo(object):
  2.     def __init__(self):
  3.         self.data=0
  4.     def __eq__(self, other):
  5.         if self is other:
  6.             return True
  7.         else:
  8.             return self.data == data
  9.  
  10. objA = Foo()
  11. objA.data = 1
  12.  
  13. objB = Foo()
  14. objB.data = 1
  15.  
  16. mylist = [objA]

Puede ser que tu objeto tenga algun tipo de id, entonces solo necesitarías checar el id. Porque tal vez los otros campos son irrelevantes para determinar la igualdad. Pero eso lo defines tu.

Etiquetas: gui, ip, objeto
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 15:23.