Multi-row python data entry

I would like to understand how to input various data (int, float, str...) per line but repeatedly (i.e. in multiple lines) so that I can save each given entry.

I understand that I will have to use a list to store each entry and, using split, I can input multiple data in the same row, but I get lost when it comes to doing this with multiple rows.

For example:

linha = input().split()

lista = []
for item in range(5):
    x = int(linha[item])
    lista.append(x)
print(lista)

This code gives me a line with several (integer) input data, I would like to repeat this process in as many rows as I want and with the various types of data I want. However, as a beginner, I still haven't gotten used to the syntax.

Author: zangs, 2019-09-26

2 answers

The function input() always returns a string, to work with other types of data we need to manipulate this string, so we go in parts.


Receive multiple values

We can solve this problem with different approaches, example:

Receiving all values at once.

We can receive a string with all the values separated by whitespace and use the str.split() to "break" this string in a list of strings. Example:

linha = input("Digite os valores separados por espaço")
# ex.: '1 2 3 4 5'
valores = linha.split()
# ['1', '2', '3', '4', '5']

If you want to convert all values to integer you can use:

  • A for to iterate on the values, convert the value, and then add to the result list with list.append().

    linha = input("Digite os valores separados por espaço")
    valores = []
    
    for valor in linha.split():
        valores.append(int(valor))
    
  • The function map to apply a function to all items in an iterable and create a new list with the result of the function for each position of the list.

    linha = input("Digite os valores separados por espaço")
    valores = linha.split()
    valores_convertidos = map(int, valores)
    
  • A list comprehension to iterate and convert all values:

    linha = input("Digite os valores separados por espaço")
    valores = linha.split()
    valores_convertidos = [int(valor) for valor in valores]
    

Getting one value at a time

You can receive an indefinite number of inputs by using a loop and setting a stop criterion.

For example, receive integers while the user enters valid values:

valores = []

while True:
    try:
        linha = int(input("Digite um número:"))
    except ValueError:
        print("Valor inválido, saindo do loop")
        break

    valores.append(linha)

In the above code I am creating an "infinite" loop that will repeat itself while the conversion of user input to int does not fail. When it fails it will launch a ValueError running the break inside except


Receiving a specific number of variables with pre-defined types

You can receive a specific number of inputs using the function range() as you yourself posted in your question:

valores = []

for _ in range(5):
    valor = input("Digite algo: ")
    valores.append(valor)

The next step is to define the types of data we should receive. We could use integers or even strings to define data types.

Example:

# 0: int
# 1: str
# 2: float
tipos = [0, 1, 1, 0, 2]
valores = []

for tipo in tipos:
    valor = input("Digite algo: ")

    if tipo == 0:
        valores.append(int(valor))
    elif tipo == 1:
        valores.append(valor)  # já é string
    elif tipo ==2:
        valores.append(float(valor))
    else:
        print("Tipo inválido, nenhum valor adicionado")

I'm not going to go much deeper into the improvements that could be made in the above code as it's just a demonstration of how it could be done.

Instead of having multiple if for each type you would like to have, you could use a list of functions that receive a string and return the type you want. In python, functions are "first class citizens" , that means you can pass them as parameters to other functions, assign them to variables, etc...

Then it is possible to do something like:

meu_int = int
valor = meu_int("10")
print(valor)  # 10

Applying this concept, redoing the example and removing the if would be:

tipos = [int, str, str, int, float]
valores = []

for tipo in tipos:
    valor = input("Digite algo: ")
    valores.append(tipo(valor))

code rolling no Repl.it

This way you are specifying that you want the user to enter 5 values, they being an integer, 2 strings, 1 integer, and 1 float, respectively. Not to mention that you can create your own functions or classes that receive a string as input and return an object of the type you want.

Conclusion

Since the subject is generic, it turned out that the answer got a little broad, but the important thing is that you understand that there are several approaches to the same problem and I hope I have given enough material for you to have a starting point for new studies and new questions.

 2
Author: fernandosavio, 2019-09-27 17:33:34

Abuse and use of try

texto = '''1
teste
1.5
balb
512

1,4'''
# Separa String por linhas e cria uma lista
lst = texto.split('\n')

lst_tratada = []
# Para cada valor que estiver na lista
for i in lst:
    # Tenta registrar o valor como int e vai para o próximo laço, senão continua
    try:
        lst_tratada.append(int(i))
        continue
    except:
        pass
    # Tenta registrar o valor como float e vai para o próximo laço, senão continua
    try:
        lst_tratada.append(float(i))
        continue
    except:
        # Se não conseguir nenhum dos dois, tratar como string
        lst_tratada.append(i)

print(lst_tratada)

A simpler approach, from a method:

def var_parser(x):
    try: # Tenta retornar x como inteiro
        return int(x)
    except: # Se não obtiver exito, continuar
        pass
    try: # Tenta retornar x como float
        return float(x)
    except: # Se não obtive exito, retornar x 
        return x


texto = '''1
teste
1.5
balb
512

1,4'''

lst = texto.split('\n')

lst_tratada = []
for i in lst:
    lst_tratada.append(var_parser(i))

print(lst_tratada)
 0
Author: SakuraFreak, 2019-09-26 20:06:47