0

Me estoy iniciando en clases en este excelente lenguaje y tengo el siguiente código:

class usuario: #clase con la que defino que parametros voy a capturar
    def __init__(self, id, nombre, apellido, edad, tiempo_conocido, asignado): #asignacion del metodo con las variables necesarias
        self.id = id
        self.nombre = nombre
        self.apellido = apellido        #Asignacion de variables al metodo
        self.edad = edad
        self.tiempo_conocido = tiempo_conocido
        self.asignado = asignado
        self.lista = lista

def Captura():
    usuario.asignado = int(input("Usuarios a capturar (maximo 5!!): "))
    for i in range(0, usuario.asignado): #Con este for agrego los usuarios de manera consecutiva en el rango establecido
        usuario.id = input("\nId del usuario: ")
        usuario.nombre = input("Nombre del usuario: ")
        usuario.apellido = input("Apellido del usuario: ")
        usuario.edad = input("Edad del usuario: ")
        usuario.tiempo_conocido = input("Tiempo de haber conocido al usuario: ")    
        usuario.final = usuario.asignado

def MuestraUsuario():   #Funcion que me permite mostrar a los usuarios capturados...
    for i in range(0, usuario.final):
        print ("\nId del usuario: ", usuario.id)
        print ("El nombre fue: ", usuario.nombre)
        print ("El apellido del usuario fue: ", usuario.apellido)
        print ("La edad fue: ", usuario.edad)
        print ("El tiempo de haberlo conocido fue de: ", usuario.tiempo_conocido)      


def BuscarUsuario():
    a = input("Qué dato busco? ")
    if a in usuario.nombre or a in usuario.id or a in usuario.apellido or a in usuario.edad or a in usuario.tiempo_conocido:
        print("*****************************")
        print ("*El elemento se encuentra!  *")
        print("*****************************")

    else:
        print("*****************************")
        print("*El elemento no esta...      *") 
        print("*****************************")        

def Ordenar():
  pass    

def menu():
    print ("Menu de usuarios! \nSelecciona una opcion: \n1.Captura\n2.Muestra de los datos capturados\n3.Busca algun dato\n4.Ordenar los elementos\n5.Salir")
    a = int(input("\nSeleccion: "))

    if a == 1:
        Captura()
        b = int(input("Deseas regresar al menu? 1 = si 2 = no: "))
        if b == 1:
            menu()
        if b == 2:
            print ("Hasta luego!")
    if a == 2:
        MuestraUsuario()
        b = int(input("Deseas regresar al menu? 1 = si 2 = no: "))
        if b == 1:
            menu()
        if b == 2:
            print ("Hasta luego!")        

    if a == 3:
        BuscarUsuario()
        b = int(input("Deseas regresar al menu? 1 = si 2 = no: "))
        if b == 1:
            menu()
        if b == 2:
            print ("Hasta luego!")        

    if a == 4:
        Ordenar()
        b = int(input("Deseas regresar al menu? 1 = si 2 = no: "))
        if b == 1:
            menu()
        if b == 2:
            print ("Hasta luego!")                


    if a == 5:
        print ("Hasta luego!")

menu()

Mi problema es que no logro hacer que en mi función mostrar me despliegue los usuarios que capturo (solo logro mostrar 1). ¿Cuál es el error?

FJSevilla
  • 55,603
  • 7
  • 35
  • 58

1 Answers1

0

El problema es que en ningún momento estas instanciando nuevos objetos de la clase y tampoco guardas las referencias de cada uno de ellos en algún contenedor, de forma que puedas luego iterar sobre todos los usuarios y hacer referencia a cada una de las instancias.

Cuando haces usuario.id estás creando un nuevo atributo de clase llamado id (que es compartido por todas las instancias) en vez de dar un valor al atributo de instancia id mediante el __init__. (Puedes mirarte esta pregunta relacionada para más información: Diferencia entre variables de instancia y variable de clase en python)

Un ejemplo para ilustrarlo usando una lista:

class Usuario:
    def __init__(id, nombre, apellido):
        self.id = id
        self.nombre = nombre
        self.apellido  = apellido


# Lista que contendrá las referencias de cada uno de las instancias de Usuario
usuarios = []

for _ in range(1):
    # Instanciamos un nuevo objeto y pasando los argumentos al inicializador
    usuario = Usuario(1455, "Pedro", "García")
    # Añadimos la nueva instancia a la lista
    usuarios.append(usuario)

# Ahora podemos iterar sobre los usuarios
for usuario in usuarios:
    print(usuarios.nombre)

Un ejemplo de cómo podría quedar tu código es:

class Usuario:
    def __init__(self, id, nombre, apellido, edad, tiempo_conocido):
        self.id = id
        self.nombre = nombre
        self.apellido = apellido
        self.edad = edad
        self.tiempo_conocido = tiempo_conocido

    def __str__(self):
        cad  = ("Id del usuario: {}\n"
                "El nombre es: {}\n"
                "El apellido del usuario es: {}\n"
                "La edad es: {}\n"
                "El tiempo de haberlo conocido es: {}"
                )
        return cad.format(self.id, self.nombre, self.apellido,
                          self.edad, self.tiempo_conocido
                          )      


def capturar_usuarios():
    usuarios = []

    while True:
        n = int(input("Usuarios a capturar (máximo 5): "))
        if  0 < n <= 5:
            break
        print("Numero de usuarios a capturar no válido")

    for _ in range(n):
        id = input("\nId del usuario: ")
        nombre = input("Nombre del usuario: ")
        apellido = input("Apellido del usuario: ")
        edad = input("Edad del usuario: ")
        tiempo_conocido = input("Tiempo de haber conocido al usuario: ")    

        # Creamos una nueva instancia de la clase usuario
        usuario = Usuario(id, nombre, apellido, edad, tiempo_conocido)
        # Añadimos el objeto a a la lista
        usuarios.append(usuario)

    return usuarios    

def mostrar_usuarios(usuarios):
    for usuario in usuarios:
        print("=======================================================")
        print(usuario) # Llama automáticamente al método __str__ de la instancia
    print("=======================================================")    

def buscar_usuario(usuarios):
    pass

def ordenar_usuarios(usuarios):
    pass

def main():
    usuarios = []

    print("¡Menu de usuarios!\n########################",)

    while True:
        print("\nSelecciona una opcion:",
              "  1. Captura",
              "  2. Muestra de los datos capturados",
              "  3. Buscar algun dato",
              "  4. Ordenar los elementos",
              "  5. Salir\n", sep="\n"
              )

        opt = input("Seleccion: ")

        if opt == '1':
            usuarios = capturar_usuarios()

        elif opt == '2':
            mostrar_usuarios(usuarios)      

        elif opt == '3':
            buscar_usuario(usuarios)       

        elif opt == '4':
            ordenar_usuarios(usuarios)

        elif opt == '5':
            print ("¡Hasta luego!")
            return

        else:
            print("No ha ingresado una opción válida. Por favor intentelo de nuevo.")
            continue

        while True:
            opt = input("\n¿Deseas regresar al menu? (s/n): ").lower()
            if opt == 's' or opt == "si":
                break
            elif opt == 'n' or opt == "no":
                print ("¡Hasta luego!")
                return
            else:
                print ("Opción no válida.")


if __name__ == "__main__":
    main()

Ejemplo de ejecución.

Hay bastantes modificaciones con respecto al código inicial:

  • El menú se implementa de forma iterativa y no con llamadas recursivas (es más intuitivo y eficiente generalmente y no hay peligro de alcanzar el límite de recursión). Se usa if-elif-else en vez de if consecutivos, la diferencia es que en el momento en el que el if o un elif se cumple el resto no es evaluado siquiera. Si todos son if se evalúan todos aunque solo uno sea cierto, lo cual es mucho menos eficiente.
  • Ya que estamos trabajando con clases se usa el método especial __str__ para mostrar la información del usuario. Este método retorna una cadena y es llamado automáticamente cuando se imprime el objeto (print(objeto)).

  • Se ha renombrado la clase y las funciones para seguir PEP 8. Te aconsejo mirarlo cuando tengas tiempo/ganas, es una guía de estilo oficial para el código Python, son solo convenciones, pero ayudan a estandarizar tu código y a facilitar la legibilidad por terceros (una de las razones de ser de Python).

Hay muchas más cosas que podemos hacer o enfoques distintos, por ejemplo sería adecuado validar los datos ingresados para crear cada instancia de Usuario, bien en la propia función capturar_usuarios o en la clase vía properties por ejemplo.

FJSevilla
  • 55,603
  • 7
  • 35
  • 58
  • simplemente impecable, veo que me falta indagar bastante sobre las clases en Python. En serio, muchas gracias por tan elaborada y limpia respuesta. Ya con esto me voy dando más una idea de como debo estar trabajando. Nuevamente, gracias! – barra51 Mar 11 '18 at 17:26