Mais sobre entradas e saídas de dados

1. Qual a diferença entre declarar e usar uma variável?

Uma variável nada mais é que um nome associado à uma posição de memória do computador: a posição de seu bit inicial e o número de bits usados para representar aquele tipo de variável. Como a linguagem Python é interpretada, pode-se em qualquer parte declarar uma variável e depois pode-se usá-la, recebendo valores ou em expressões.

def main () :
  i = 3; # declara variavel inteira 'i' (i sendo iniciada com valor 3)
  x = 0.5; # declara variavel inteira 'x' (iniciada com 0.5)
  y = i/2; # declara variavel inteira 'y' (pois i e' inteiro => recebera' 3/2 = 1)
  # %d e' formatador para imprimir inteiro, %f para flutuante - y=%f e' para comprovar que 3/2 = 1  
  print("i=%d, x=%f, y=%f" % (i, x, y));
  ...
main();
Cód. 1. Código ilustrando a declaração de variáveis inteiras e flutuantes.

Outro conceito essencial às variáveis é o de atribuição de valor. Sua sintaxe em Python, e em muitas outras linuguagens, é usar do lado esquerdo da atribuição um nome de variável e do lado direito da atribuição uma expressão aritméitca válida. No código 1, i=0 e x=0.5 são atribuições, então funciona no Python como declaração de variável, desse modo i será variável inteira e x flutuante. tendo como lado esquerdo as variáveis i e x e como lado direito as expressões constantes 0 e 0.5.

Ainda usando como estrutura o código 1, outro exemplo de atribuição poderia ser i = n/2, que tem como lado direito a expressão n/2. Como no código 1 a variável n é do tipo inteiro, o mesmo para a constante 2 (se desejasse flutuante deveria usar 2.0), então seu resultado é o quociente da divisão inteira da divisão. Mas vale adiantar outra possibilidade de "forçar" o resultado a ser flutuante, usar o coversor de tipo: x = float(n)/2. Entretando, a expressão float(n/2) é irrelevante, produzindo o mesmo resultado que n/2 (por exemplo, para n=3, a transformação é aplicada sobre o resultado de 3/2 que é 1).

Saber mais A figura 1 ilustra a associação de espaço em memória (RAM) para duas variáveis, são associados 16 bits à variável de nome n, para guardar valores inteiros, seguido da associação de 32 bits para a variável de nome x, que deve guardar valores "reais". Nota-se que a variável "real" tem um esquema mais "complicado", ela implementa o conceito de ponto flutuante, usando o padrão IEEE 754 (o primeiro bit é o sinal s; os 8 bits seguintes correspondente ao expoente e e os últimos 23 à mantissa m - valor de x é s x m x 10e, sendo m entre 0 e 1).

Fig. 1. Representação da memória com agrupamentos em bytes (8 bits).

Procure lembrar-se: em Python, sempre que existe uma atribuição, a variável que aparece do lado esquerdo da atribuição está sendo (re)definida! Isso corresponde à sua declaração!
Isso implica que, na declaração é reservado um espaço de tamanho fixo na memória do computador, o "tamanho" desse espaço depende do tipo da variável.

2. O que são "entradas de dados" e "saídas de dados"?

Um algoritmo é uma sequência finita de passos, que ao ser aplicado à um conjunto de dados (entradas) deve produzir sempre as mesmas saídas. Por exemplo, o algoritmo da divisão ao ser aplicado sobre valores fixados a e b, deve produzir sempre o mesmo valor q (de tal forma que q * b = a).

Por outro lado, um programa, em Python ou em qualquer outra linguagem, nada mais é que a implementação de um algoritmo na referida linguagem. Desse modo, para este programa ser usado, o usuário (aquele que está executando) deve fornecer um conjunto de dados de entrada, na ordem adequada (pois a/b geralmente não é o mesmo que b/a), para que o programa possa ser executado e produzir as saídas desejadas.


Fig. 2. Ilustração da existência de um algoritmo que aplicado sobre as entradas produz as respectivas saídas.

Podemos usar o mesmo exemplo da divisão para ilustar a necessidade dos dados de entrada adequados. Para que um algoritmo para a divisão de dois números reais seja adequadamente executado, devem ser fornecidos os dois valores reais, o primeiro será o numerador e o segundo será o denominador. Assim, se o usuário digitar apenas um valor, o programa ficará parado até que ele digite o segundo valor.

Saber mais Vale observar que, em uma linguagem de programação, não existe a necessidade de implementar algo tão básico quanto à divisão de dois números, pois isso é feito por um algoritmo implementado diretamente no processador do computador. Desde a proposta do computador EDVAC, apresentada em documento de 1945 pelo matemático John von Neumann, existe uma unidade lógico/aritmética especialmente projetada para realizar as operações lógicas e aritméticas. Entretanto, nesse modelo o tratamento para "números reais" era feito com ponto fixo, enquanto hoje utilizamos ponto flutuante por permitir um maior escopo de valores.

3. Entrada e saída de dados simples: inteiro e "real" em Python 2

Na versão 2 do Python a função input() tenta interpretar as entradas como valores numéricos, se for necessário a leitura de um texto deve-se usar a função raw_input() que sempre devolve uma cadeia de caracteres (que é usualmente tratada pelo correspondente em Inglês "strings").
Desse modo, se o usuário deseja trabalhar com um valor inteiro, pode tentar forçar a conversão do que for digitado para inteiro com int(input()) (então se digitar 3.2, automaticamente converte para 3). Por exemplo: n = int(input())
O análogo deve ser feito para "reais", flutuantes, usando-se float(.). Assim, mesmo que o usuário digite 3, o valor é automaticamente convertido para 3.0: x = float(input())

O código 2 mostra a entrada de um valor inteiro (um Enter), seguido pela entrada de um valor "real" (outro Enter).

def leia1 () :
  a = int(input()); b = float(input()); # o primeiro ';' e' obrigatorio para poder usar 2 atribuicoes em uma unica linha
  print(a,b); # o finalizador ';' e' opcional

leia1(); # chama a funcao para leitura
Cód. 2. Código ilustrando a entrada para valor inteiro e para "flutuante".

Vale notar que, para o código 2, se o usuário digitar uma "cadeia de caracteres" (com letras) como primeira entrada, ele receberá uma mensagem de erro. Abaixo a mensagem de erro após digitar o número s1:
  File "codigos/introducao_leituras_python_2.py", line 2, in leia_imprima
    a = int(input()); b = float(input());
File "", line 1, in
NameError: name 's1' is not defined

4. Saída de dados formatada: inteiro, "real" e caractere em Python 2

Em Python é possível fazer impressões mais sofisticadas utilizando um formatador (%) seguido de um caractere indicando o tipo da variável ser impressa: d => "inteiro"; f => "float"; c => "caractere"; s => "string". Por exemplo, pode-se usar os comandos
    m = 2; x = 2.3; t = 'A';
    print("m=%d, x=%f, t=%c" % (m, x, t)); # imprime m, x e t


Vale notar que o quarto caractere %, imediatamente antes de (m, x, t) é para separar o texto a ser impresso dos valores a serem usados nos formatadores. Os valores estão na lista de valores (m, x, t) (que poderia usar alguma expressão em qualquer deles) a ser impressa, sendo a ordem importante. No exemplo, o primeiro formatador %d será usado para imprimir a primeira variável m, o segundo %f é associado à segunda variável t "real" e o terceiro %c é para t (caractere).

Os formatadores podem facilitar a impressão de tabelas, utilizando valores entre o símbolo de porcentagem e o tipo de variável a ser impressa, por exemplo: %3d usa 3 espaços, ajutando à direita o último, %8.3f usa 8 espaços, ajutando à direita o último e colocando o ponto decimal na terceira posição (da direita para esquerda). Experimente a linha abaixo:
    print("m=%3d, f=%8.3f, c=%2c" % (m, f, c));

Na tabela 1, apresentamos códigos ilustrativos para entrada e saída de valores inteiros e flutuantes. Outro aspecto importante que é ilustrado é o tratamento de divisão no Python 2, que pode forçar a divisão inteira com a // b (assim 3.2 // 2 resulta 1). No Python 3, existe uma diferença no tratamento de a / b, que será sempre a divisão de "real".

Tab. 1. Exemplo de códigos para entrada e saída de inteiros e "reais" para o Python 2
Python 2: código com formatador Exemplo para entradas e respectivas saídas
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
18
20
21
22
23
24
25
26
# No Python 2 "input()" pega um linha inteira como caracteres
# Se for necessario usar valores numericos, precisa converter um a um

def leia_imprima () :
  # Ilustrando a entrada de um texto:
  texto = raw_input();# Forca interpretar como um texto
  print("Foi digitado: %s" % texto); # formatador %s e' para "string"

  # Ilustrando entrada de inteiro e divisao inteira/"real"
  n = int(input()); # "int(.)" tenta converter para inteiro
  m1 = n//2;     # forca divisao inteira => m1 sera' "int"
  m2 = n/2;      # se n "real" => m2 sera' "real"
  print("n=%d=%f, m1=%f=%d, m2=%f=%d" % (n,n,m1,m1,m2,m2));

  # Ilustrando que nova atribuicao => nova definicao
  n = 4.7; # Nova atribuicao => redeclara, agora float
  m1 = 3*n; # idem, m1 passa a ser "float"
  print("n=%f, m1=%f != %d" % (n,m1,m1)); 

  # Ilustrando entrada de flutuante e divisao "real"
  n = float(input()); # "float(.)" tenta converter para flutuante
  m1 = n//2;     # divisao inteira => m1 sera' "int"
  m2 = n/2;      # divisao "real"  => m2 sera' "float"
  print("n=%d=%f, m1=%f=%d, m2=%f!=%d" % (n,n,m1,m1,m2,m2));

leia_imprima()





Entrada: este e' um teste
Saída:   Foi digitado: este e' um teste


Entrada: 3.2
Explicação: 3//2 é quociente da divisão inteira, logo m1 receberá o valor 1
Explicação: 3/2 é quociente da divisão "real", logo m2 receberá o valor 1.0
Saída:   n=3=3.000000, m1=1.000000=1, m2=1.000000=1


Explicação: nova definição para variável n que passou a ser do tipo flutuante com valor 4.7
Explicação: nova definição para variável m1 que passou a ser do tipo flutuante com valor 14.1
Saída:   n=4.700000, m1=14.100000 != 14


Entrada: 3.2
Explicação: m1 recebe quociente da divisão inteira por 2, logo m1 receberá o valor 1
Explicação: m2 recebe divisão "real", logo m2 receberá o valor 1.6
Saída:   n=3=3.200000, m1=1.000000=1, m2=1.600000!=1


Se o usuário desejar inserir outra coisa (em geral uma cadeia de caracteres - "string") deve-se usar uma função especial (vide raw_input a seguir).

5. Entrada de dados: vários valores em uma só linha no Python 2

Como citado acima, a versão 2 do Pythonprioridade às entradas serem valores numéricos, assim usando apenas input() automaticamente tenta-se interpretar o que foi digitado como número. Se forem digitados vários valores ou alguma palavra ocorre erro (File "", line 1).

Assim, se for necessário entrar vários valores de uma só vez deve-se usar uma sequência de comandos:

  1. input(): a partir do Python 3 esse comando sempre faz leitura de sequência de caracteres (cadeia de caracteres ou "string");
  2. map(tipo, iterador): para aplicar uma função (no caso, o conversor de tipo) sobre cada um dos elementos de uma estrutura que permite iteração (como mapa);
  3. list(iterador): devolve uma lista com todos de uma estrutura que permite iteração (como mapa).
p>

Por exemplo, para digitar as dimensões de uma matriz e seu maior e menor valor em um único ENTER, pode-se usar o comando:

  m, n = map(int, raw_input().split()); # raw_input pega a "string" digitada "2 4"
  print("m=%d, n=%d" % (m, n));
  
A primeira linha corresponde a uma sequência de passos:
  1. raw_input() pegar a "string" digitada (e.g. supor ter sido digitado 2 4 ENTER;
  2. split() quebra a "string", gerando uma lista (e.g. ["2", "4"])
  3. map com parâmetro int aplica um algoritmo de conversão aplicado à cada item, transformando-os em inteiro (e.g. [2, 4])

Mas com a conversão é uniforme na função map, se tiver misturas de valores seria necessário algum "truque". Por exemplo, suponha que precise ser digitado 2 inteiros seguindos de 2 "floats" (em um único ENTER), pode-se usar o conversor para o tipo de "maior tamanho" ("float" no caso) e depois fazer mais uma conversão:

   m, n, x, y = map(float, raw_input().split()); # raw_input pega a "string" digitada "2 4 3.1 6.1"   
   m, n = map(int, [m, n]); # gere uma lista [m,n] e a converta para inteiro
A primeira linha tem comportamento análogo ao código anterior, mas convertendo para "float" (e não "int"):
  1. raw_input() pegar a "string" digitada (e.g. supor ter sido digitado 2 4 3.1 6.1 ENTER;
  2. split() quebra a "string", gerando uma lista (e.g. ("2", "4", "3.1", "6.1"))
  3. map com parâmetro float aplica um algoritmo de conversão em cada item tornando-os "float" (e.g. (2.0, 4.0, 3.1, 6.1))
  4. map com parâmetro int aplica um algoritmo de conversão em cada item tornando-os "int" (e.g. (2, 4))

Para o código anterior, se rodá-lo com o Python 2, supondo a primeira linha de entrada ser 2 4 e a segunda 2 4 3.1 6.1, produzirá o seguinte resultado:


2 4
m=2, n=4
2 4 3.1 6.1
m=2, n=4, x=3.100000, y=6.100000
Fig. 3. Ilustração do erro ao supor que existe comentários aninhados em Python.

Leônidas de Oliveira Brandão
http://line.ime.usp.br

Alterações :
2021/04/22: pequenos acertos, alterações visibilidade desse rodapé
2021/04/20: pequenas correções
2020/08/14: novo formato, pequenas revisões
2020/07/06: Segunda, 06 Julho 2020, 23:30