IIC2233-2015-2 / syllabus

Página principal del curso
47 stars 57 forks source link

Problema con heredar #299

Closed trencoret closed 9 years ago

trencoret commented 9 years ago

Tengo una duda de heredar en general. Como se crean dos objetos diferentes que tengan las mismas caracteristicas pero que tengan id diferentes? Con el siguiente ejemplo sacado de las clases, si yo creo los dos objetos tienen id diferentes, pero las caracteristicas no. Pregunto esto porque si yo despues le cambio la caracteristica a un objeto, se le cambia la caracterisitica al otro objeto, y no quiero que pase eso. Como lo hago si no? Muchas gracias!

class ContactList(list):

    # buscar es un método específico de esta sub-clase
    def buscar(self, nombre):
        matches = []

        for contacto in self:
            if nombre in contacto.nombre:
                matches.append(contacto)

        return matches

class Contacto:

    # Contacto se compone de una lista de contactos del tipo ContactList
    # contactos_list = [] #así sería para usar una lista común y corriente
    contactos_list = ContactList()

    def __init__(self, nombre, email):
        self.nombre = nombre
        self.email = email
        Contacto.contactos_list.append(self) # el método append() es heredado de la clase List()

class Familiar(Contacto):

    def __init__(self, nombre, email, relacion): # Overriding sobre el método __init__()
        super().__init__(nombre, email) # Obtiene la instancia del padre y llama a su funcion __init__
        self.relacion = relacion

p1 = Familiar(nombre = "Juan Gomez", email = "jc@hotmail.com", relacion = "padre")
p2 = Familiar(nombre = "Juan Gomez", email = "jc@hotmail.com", relacion = "padre")
print(id(p1))
print(id(p2))

>>>4346490608
>>>4346490776

print(id(p1.nombre))
print(id(p2.nombre))

>>> 4346502320
>>> 4346502320
trencoret commented 9 years ago

@bamavrakis @jecastro1 @mrpatiwi @mbucchi

lopezjurip commented 9 years ago

https://docs.python.org/3/library/functions.html#id

Al parecer, el intérprete de Python puede guardar en la misma posición los strings iguales para ahorrar memoria. Como p1 y p2 se llaman igual (Juan Gomez), entonces las id de sus nombres son las mismas.

Ahora, los strings en Python son inmutables, así que no se va a modificar uno si modificas "el otro". Sino que tienes que crear un string nuevo y reemplazarlo.

lopezjurip commented 9 years ago

Tengo mis dudas, acabo de probar esto y el id es distinto para palabras compuestas

>>> a = "algo"
>>> id(a)
4330435056
>>> id("algo")
4330435056
>>> b = "Patricio Lopez"
>>> id(b)
4330442992
>>> id("Patricio Lopez")
4330443056
trencoret commented 9 years ago

Si, acabo de comprobar lo mismo, estaba haciendo mal la heredada. Muchas gracias @mrpatiwi por la duda! ahora voy a debugear mi codigo.

trencoret commented 9 years ago

@mrpatiwi Tengo un problema.. Trate de quitar toda la informacion que pueda ser problematica. Pero si corres eso, me cambia el disponible de ambos barcos

class Arma:
    def __init__(self):
        self.disponible = True

    def usar(self):
        self.disponible = False

class Tomahawk(Arma):
    def __init__(self):
        Arma.__init__(self)

class Vehiculo:
    def __init__(self, armas):
        self.armas = armas

class Barco_pequeno(Vehiculo):

    def __init__(self, armas = [Tomahawk()]):
        Vehiculo.__init__(self,armas= armas)

b1 = Barco_pequeno()
b2 = Barco_pequeno()

print(id(b1))
print(id(b2))
print('s')
print(id(b1.armas[0].disponible))
print(id(b2.armas[0].disponible))
print('s')
b1.armas[0].usar()
print(id(b1.armas[0].disponible))
print(id(b2.armas[0].disponible))
print('s')
lopezjurip commented 9 years ago
  1. Está mal formateado la issue
  2. Estás usando mal la herencia, en la llamada a la super clase, revisa los apuntes.
  3. En Python nunca es bueno definir una lista/arreglo como parámetro por defecto. Porque perduran entre distintas llamadas. Ver: https://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument
trencoret commented 9 years ago
  1. Como la formateo para que salga el texto limpio?
  2. He estado revisando este problema hace como 3 horas, y revisando los apuntes no se por que esta mal hecha la heredacion... Ayuda!! ajaj
  3. Gracias por el dato!
lopezjurip commented 9 years ago
  1. https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code Igual te lo corregí, pero para que sepas.
  2. Deberías hacerlo así:
class Tomahawk(Arma):
    def __init__(self):
        super().__init__()
lopezjurip commented 9 years ago

De hecho, si no vas a poner nada en el constructor de una subclase. Puedes omitirlo:

class Tomahawk(Arma):
    pass

Este código funciona igual que antes.

trencoret commented 9 years ago

Usar el super() y el nombre de la clase creo que es lo mismo, aunque el nombre de la clase es para no heredar dos veces (problema del diamante), pero si solo heredas de una da lo misma... Cambiandolo, igual sigue el problema..


class Arma:
    def __init__(self):
        self.disponible = True

    def usar(self):
        self.disponible = False

class Tomahawk(Arma):
    pass

class Vehiculo:
    def __init__(self, armas):
        self.armas = armas

class Barco_pequeno(Vehiculo):

    def __init__(self, armas = [Tomahawk()]):
        super().__init__(armas= armas)

b1 = Barco_pequeno()
b2 = Barco_pequeno()

print(id(b1))
print(id(b2))
print('s')
print(id(b1.armas[0].disponible))
print(id(b2.armas[0].disponible))
print('s')
b1.armas[0].usar()
print(id(b1.armas[0].disponible))
print(id(b2.armas[0].disponible))
print('s')
lopezjurip commented 9 years ago
class Barco_pequeno(Vehiculo):
    def __init__(self, armas=None):
        armas = armas if armas else [Tomahawk()]
        super().__init__(armas=armas)
trencoret commented 9 years ago

Pato, mis respetos jajaj. Muchas gracias! Ahi me funciono.

Saludos