Studying lists

Asked

Viewed 94 times

1

I have two lists, the first call from cadastro and the second call from entrada.

I remove an item from the list entrada and then I want to return this item in case it’s on the list cadastro, but I can only do that with the first inserted item.

Otherwise always returns the second condition: "Name is not in the list".

cadastro = []
entrada = []
saida = []


def opc():
    cad = input('(1) Acessar cadastro - (2) Acessar entradas - (3) Registrar entrada - (4) Registrar saida:'
                ' - (5) Registrar retorno: \n -> ')

    if cad == '1':
        for c in cadastro:
            print(c)
        opc()

    elif cad == '2':
        for s in entrada:
            print(s)
        opc()

    elif cad == '3':
        entrar()

    elif cad == '4':
        sair()

    elif cad == '5':
        retorno()


def dados():
    nome = str(input('nome: '))

    cadastro.append({'nome': nome}),
    entrada.append({'nome': nome})


def entrar():
    dados()
    opc()


def sair():
    nome = str(input('Nome: '))

    for i in range(0, len(entrada)):
        user = entrada[i].get('nome')
        if user == nome:
            print(user)
            entrada.remove(entrada[i])
            opc()


def retorno():
    nome = str(input('Nome: '))

    for i in range(0, len(cadastro)):
        user = cadastro[i].get('nome')
        if nome == user:
            entrada.append(cadastro[i])
            print(entrada)
            opc()
        else:
            print('Nome não se encontra na lista.')
        opc()


opc()

1 answer

1


First of all, don’t call the function within itself, as you did with opc().

Although "working", it is not ideal. This is because each time a function is called, it is "stacked" (placed on the execution stack). And as long as the function doesn’t return, it stays there taking up space in the stack.

I mean, on your show, you call opc(), who can call herself again, or call one of the other functions, who calls opc() again, which calls itself or one of the functions it calls opc() again, etc... As there is never a return of these functions, they are occupying space in the stack. And if the program runs for too long, it might end up popping the stack (see here an example, scroll to the bottom of the page and see the RecursionError).

Calling a function within itself is called "recursion", and is a resource that most of the time you won’t need.

Anyway, if you want something to repeat over and over again, use a loop simple. From what I understand you want something like this:

cadastro = []
entrada = []
saida = []

def dados():
    nome = input('nome: ')
    cadastro.append(nome)
    entrada.append(nome)

def sair():
    nome = input('Nome: ')

    for i, user in enumerate(entrada):
        if user == nome:
            print(user)
            del entrada[i]
            break # se já encontrei, interrompe o for

def retorno():
    nome = input('Nome: ')
    for nome_cadastrado in cadastro:
        if nome == nome_cadastrado:
            entrada.append(nome_cadastrado)
            print(entrada)
            break # se já encontrou, interrompe o for
    else:
        print('Nome não se encontra na lista.')

while True: # loop infinito
    cad = input('(1) Acessar cadastro - (2) Acessar entradas - (3) Registrar entrada - (4) Registrar saida:'
                ' - (5) Registrar retorno: \n -> ')

    if cad == '1':
        for c in cadastro:
            print(c)
    elif cad == '2':
        for s in entrada:
            print(s)
    elif cad == '3':
        dados()
    elif cad == '4':
        sair()
    elif cad == '5':
        retorno()

I use while True, which creates a loop infinite. The difference to keep calling the function opc several times within itself (or within other functions) indefinitely is that here there are not several calls being stacked and so will not occur the RecursionError. Don’t use recursion where you don’t need it - and most of the time loop simple as this solves.

Note also that input already returns a string, so do str(input(...)) is redundant and unnecessary.

The function retorno didn’t work because you put the else within the for, that is, for each element, it sees if it is the name typed, and for each element that is not equal to that name, it prints the message. I switched to interrupt the for (with the break) once you find the name (because if you have already found it, it makes no sense to continue the loop). And the else is from for, not of if (other languages do not have this feature, but Python does), and it falls into else if the loop is not interrupted by a break (that is, if the name is not on the list).

And in function sair I used del to delete the element. Detail: In general, it is not a good idea to delete elements from the list in the same loop that iterates on it (as explained here, here and here), but in this particular case I remove and already interrupt the loop with break, then the problems mentioned in the links already indicated do not occur. I also used enumerate to iterate through the indexes along with the list elements.

And I’ve changed something else: I’m just keeping the names on the lists instead of a dictionary. Unless you are going to save more information on each record, there is not much gain in using dictionaries here.

  • 1

    Vlw fera. thank you so much for the tips was of great help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.