<!--
 Introdução à Programação - 2017 - Prof. Leoônidas de Oliveira Brandão
 Introdução aos vetores em Python
 @url: ./codigos/varias_entradas_saidas.py
 LInE (Laboratory of Informatics in Education) - http://www.usp.br/line
 IME - USP
 Material didático
 Pode usar livrevemente este material para fins não comerciais, devendo sempre fazer referência à autoria.
 Sugestões/apontamento são bem vindos: leo@ime.usp.br (favor indicar no assunto "material de introducao 'a programacao")
 Prof. Leônidas de Oliveira Brandão
 http://www.ime.usp.br/~leo
 http://line.ime.usp.br
 http://www.matemtica.br
-->

  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  <meta name='keywords' content='mac0122, material, professores, leonidas de oliveira brandao'>
  <link rel='stylesheet' type='text/css' href='css_img_js_conf/all.css'>
  <link rel='stylesheet' type='text/css' href='css_img_js_conf/line_introducao_programacao.css'>
  <script src="css_img_js_conf/defineLInE.js"></script> <!-- para referencias 'a documentos internos -->
<div class="pagina">


<!--
<center><p>[
  <a href="#" title=""></a> &nbsp; | &nbsp;
  <a href="#memoria" title=""></a> &nbsp; &nbsp;
 ]</p>
</center>
-->


<p class="secao">Introdução aos vetores em <i>Python</i></p>

<p>
  Como estudado no
  <a href="#" onclick="trocaPagina('introducao_vetores.html')" title="introducao_vetores.html">texto a respeito do conceito de vetores</a>,
  um vetor é uma sequência de dados ocupando posições consecutivas de memória e por isso existe uma ordem
  natural (o primeiro elemento, o segundo e assim por diante).
  A grande vantagem de usar vetor é poder trabalhar com um grande número de variáveis utilizando um único
  nome (para a variável). Para isso existe uma sintaxe especial para pegar elementos do vetor em posições
  específicas (como o primeiro elemento ou o décimo elemento).
</p>

<p>
A linguagem <i>Python</i> encapsula bastante o conceito de vetor, agregando funcionalidades e por isso
geralmente o material didático sobre <i>vetores</i> em <i>Python</i> utiliza o nome <i>lista</i>.
</p>


<bloco1>Neste texto:
   <a class="" title="como ler varios dados entradas com unico ENTER" href="#entradas_saidas">entradas e saídas</a>;
   <a class="" title="definir e imprimir um vetor" href="#define">definir/imprimir vetor</a>;
   <a class="" title="definir e imprimir string" href="#string">definir "string"</a>;
   <a class="" title="sobre referencia e copia de vetores" href="#referencia">referência a listas</a>;
   <a class="" title="definir e imprimir uma matriz" href="#matriz">definir/imprimir matriz</a>.
</bloco1>

<br/>

<!-- secao -->
<a name="entradas_saidas">
<p class="secao">1. Como ler vários dados de uma só vez</p>
</a>

<p>
  Em <i>Python</i> entrar vários dados de uma só vez não é tão trivial, é preciso processamento para recuperar os valores,
  para isso é preciso ler a entrada toda como uma <i>cadeia de caracteres</i> (<i>string</i>).
  Mais ainda, no <i>Python 2</i> existe uma função especial para isso, a <tt>raw_input</tt>, que no <i>Python 3</i> sumiu!
</p>

<p>
  O truque básico é ler como <i>string</i>, quebrar em itens (usando os separadores, geralmente espaço em branco) e por fim
  converter para o tipo desejado.
  Por exemplo, para ler dois valores, o primeiro sendo inteiro e o seguindo flutuante, podemos fazer:
  <br/>
  <center>
  <i>Tab. 1. Exemplos de técnicas para ler vários dados com um único <i>ENTER</i> em <i>Python</i>.</i>
  <table style="border: 1px solid black;">
  <tr style="border: 1px solid black;"><td><i>Python 2</i></td> <td>&nbsp;&nbsp;</td> <td><i>Python 3</i></td></tr>
  <tr>
   <td><tt style="font-size: 0.8em;">linha = raw_input();<br/>
itens = linha.split();<br/>
n, val = int(itens[0]), float(itens[1]);<br/>
<verm>print</verm>("n=%d, val=%f" % (n,val));</td><td>&nbsp;</td>
   <td><tt style="font-size: 0.8em;">linha = input();<br/>
itens = linha.split();<br/>
n, val = int(itens[0]), float(itens[1]);<br/>
<verm>print</verm>("n=%d, val=%f" % (n,val));</td></tr>
  </table></center>
</p>

<p>
  Note que usamos um formatador especial <tt>%d</tt> para valores inteiros e <tt>%f</tt> para ponto flutuante.
</p>

<p>
  No exemplo acima precisamos converter o primeiro item para inteiro e o segundo para <i>flutuante</i>.
  Entretanto se todos itens forem de mesmo tipo, existe uma função que realiza automática o laço percorrendo
  todos os elementos e convertendo um a uma, é o mapeamento <tt>map</tt>, como ilustrado abaixo.
  Experimente o código com um única linha de entrada de dados: <tt>0.0 1.0 1.5 2.0 3.0 3.5 &lt;ENTER&gt;</tt>.
  <br/>
  <center>
  <i>Tab. 2. Exemplos de técnicas para ler vários dados "reais" com um único <i>ENTER</i> em <i>Python</i>.</i>
  <table style="border: 1px solid black;">
  <tr style="border: 1px solid black;"><td><i>Python 2</i></td> <td>&nbsp;&nbsp;</td> <td><i>Python 3</i></td></tr>
  <tr>
   <td><tt style="font-size: 0.8em;">linha = raw_input();<br/>
itens = linha.split();<br/>
vetor = map(float, itens); <cyan># Erro se tentar: map(int, itens)</cyan><br/>
tam = len(vetor);<br/>
for i in range(tam) :<br/>
  &nbsp;&nbsp;<verm>print</verm>("%2d | %4.1f" % (i,vetor[i]));</td><td>&nbsp;</td>
   <td><tt style="font-size: 0.8em;">linha = input();
itens = linha.split();<br/>
vetor = map(float, itens); <cyan># Erro se tentar: map(int, itens)</cyan><br/>
tam = len(vetor);<br/>
for i in range(tam) :<br/>
  &nbsp;&nbsp;<verm>print</verm>("%2d | %4.1f" % (i,vetor[i]));</td></tr>
  </table></center>
</p>

<p>
  Note que os formatadores <tt>%d</tt> e <tt>%f</tt> foram usado com parâmetros, <tt>%2d</tt> e <tt>%4.1f</tt>.
  O primeiro indica que devemos ajutar 2 posições à direita e o segundo ajustar 4 posições à direito e usar apenas 1 casa
  decimal. Estes formatadores permitem saídas mais interessantes, em particular a construção de tabelas.
</p>

<p>
  Pegue <a href="codigos/varias_entradas_saidas.py" title="um exemplo para testar">este código</a>
  exemplo e "brinque" com ele, altere os formatadores, troque "float" por "int", veja a mensagem de erro, acerte-a.
  Teste até estar seguro de ter entendido o <tt>raw_input</tt>, o <tt>split</tt>, o <tt>map</tt> e os formatadores
  <tt>%d</tt> e <tt>%f</tt>.

</p>

<!-- secao -->
<a name="define">
<p class="secao">2. Defininido e imprimindo uma lista</p>
</a>

<p>
  Pode-se construir uma lista em <i>Python</i> fornecendo todos seus elementos, como em:
  <tt>vet = [21, 22, 23, 24];</tt> (o finalizador <tt>;</tt> só é obrigatório se tiver mais de um comando na mesma linha).
</p>

<p>
  Pode-se também construtir uma lista em <i>Python</i> de modo interativo, agragando novo elemento a cada passo
  usando a função comando <tt>append(.)</tt>, como em:
  <tt>vet.append(10+i);</tt>, que anexa o elemento de valor <tt>10+i</tt> à lista.
</p>

<p>
  No exemplo a seguir construimos uma lista com <i>n</i> (usando o valor fixo <i>10</i> no código) elementos,
  iniciando no <i>10+i</i> e seguindo até o <i>10+n-1</i>.
  Nesse exemplo ilustramos o uso de iterador (<i>in</i>) e o anexador de novo elemento em lista (<i>append</i>).
</p>

<div class="exemplo"><i>Exemplo 1</i>. Construir uma lista e imprimir seus elementos.
</div><!-- class="exemplo" -->
<div class="codigo">
  <pre># Python2 para 'print' sem pular linha : <verm>print</verm>("*" , end = "");
from __future__ import print_function

n = 10;

# Definir vetor/lista com: (10,11,12,13,...10+n-1)
vet = []; <cyan># define um vetor vazio</cyan>
for i in range(0, n, 1) : <cyan># ou mais simples neste caso "for i in range(n)"</cyan>
  vet.append(10+i); <cyan># anexe mais um elemento `a lista</cyan>
<cyan># Imprime o vetor/lista de uma so' vez (na mesma linha)</cyan>
<verm>print</verm>("\nO vetor: ", end=""); <cyan># informe o que vira impresso a seguir (na mesma linha devido ao parametro end=""</cyan>
<verm>print</verm>(vet);

# Imprimir vet em linha unica na forma "( 0,  0) ( 1,   1)..."
<verm>print</verm>("\nNovamente o vetor impresso de 2 modos: "); <cyan># informe o que vira impresso a seguir (e "quebre" a linha)</cyan>
i = 0;
for item in vet : <cyan># "item in vet" e' um iterador, item comeca em vet[0], depois vet[1] e assim por diante</cyan>
  <verm>print</verm>("(%2d, %2d) " % (item, vet[i]), end="");
  i += 1;
<verm>print</verm>(); <cyan># quebre a linha</cyan></pre>
</div><!-- class="codigo" -->


<!-- secao -->
<a name="string">
<p class="secao">3. Defininido uma <i>cadeia de caracteres</i> ("string")</p>
</a>

<p>
  Em <i>Python</i> é possível definir um vetor com caracteres, formando uma palavra, ou seja, uma <i>cadeia de caracteres</i>,
  que abreviadamente é denominada "<i>string</i>".
  Para isso pode-se fazer uma atribuição como constante ou ler os dados como palavra. Isso é ilustrado no exemplo abaixo.
</p>

<div class="exemplo"><i>Exemplo 2</i>. Trabalhando com "strings". Uma "string" fixa e digitar uma frase, imprimindo o número
  de caracteres nela.
</div><!-- class="exemplo" -->
<div class="codigo">
<pre># Definir "string"
string = "0123456789abcdefghih"; <cyan># (1)</cyan>
# Imprimir cada caractere da string com seu codigo ASCII
<verm>print</verm>("\nImprime caracteres e seus codigos ASCII na forma de tabela\nColuna 1 => caractere; coluna 2 => seu codigo ASCII");
for char in string : <cyan># iterador</cyan>
   <verm>print</verm>("%20c : %3d" % (char, ord(char))); <cyan># funcao ord(.) devolve codigo ASCII do caractere parametro</cyan>
<verm>print</verm>(); <cyan># quebre a linha</cyan>

# Agora um entrada de dados via teclado e pegando uma frase como "string" (o ENTER finaliza a frase)
<verm>print</verm>("Digite uma frase e tecle ENTER/CR");
string = raw_input(); <cyan># no Python 2 e' obrigatorio usar a funcao 'raw_input' (que tambem funciona no 3)</cyan>
<verm>print</verm>("Foi digitada uma frase com %d caracteres: %s" % (len(string), string));

# Observacao: se definiu um vetor como "string" como em (1) acima, NAO e' possivel alterar a "string", por exemplo,
# o comando abaixo resulta erro "TypeError: 'str' object does not support item assignment"
# string[2] = '*'; <cyan># isso resultaria erro! experimente</cyan></pre>
</div><!-- class="codigo" -->


<!-- secao -->
<a name="referencia">
<p class="secao">4. Sobre copiar ou referenciar um vetor/lista</p>
</a>

<p>
  Ao declarar uma <i>lista/tupla</i>, significa que associamos um nome de variável à uma sequência de posições de memória,
  sendo que cada item pode ter um tamanho distinto dos demais,
  como em <tt>l = [1,[2],"tres"];</tt>.
  Uma diferença essencial entre <i>lista</i> (como <tt>l = [1,2,3];</tt>) e <i>tupla</i> (como <tt>l = (1,2,3);</tt>)
  é que uma <i>lista</i> é <i>mutável</i> (<i>que pode ser altedo</i>) e
  <i>tupla</i> é <i>imutável</i> (impossível de alterar algum elemento).
  <center>
   <img src="img/int_vet_apontador_menor.png" title="representacao de vetor em memoria com indicacao de endereco ocupado"/>
  </center>
</p>

<p>
  Por exemplo, ao declarar a <i>tupla</i> com <tt>v = (1,2,3);</tt>, além do espaćo com informaćões sobre a <i>tupla</i>, são
  reservadas 3 posições de memória, uma para cada elemento da <i>tupla</i>.
  Deve-se destacar que usar um comando do tipo <tt>aux = v;</tt>, seja <i>v</i> uma lista ou uma <i>tupla</i>,
  <i>não implica em copiar</i> <i>v</i>, mas sim ter uma nova referência para <i>v</i>.
  Assim, no caso de <i>lista</i>, que portanto pode ser alterada, ao usar os comandos<br/>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>v = [1,2,3]; aux = v; aux[2] = -1; <verm>print</verm>(v);</tt><br/>
  será impresso na tela: <tt>[1, 2, -1]</tt>, ou seja, o elemento da posićão 2 de <i>v</i> foi alterado para <i>-1</i>.
</p>

<p>
  Mas existe uma funćão em uma biblioteca <i>Python</i> que copia listas genéricas (<tt>copy</tt>).
  No exemplo a seguir ilustramos como fazer copia de <i>listas</i> ou <i>tuplas</i>.
</p>

<div class="exemplo"><i>Exemplo 3</i>. Construindo um vetor e imprimindo seus elementos via um apontador.
</div><!-- class="exemplo" -->
<div class="codigo">
<pre>import copy <cyan># para funcao 'copy(.)'</cyan>
<verm>def</verm> copiar (lst_tpl) : <cyan># funcao para copiar elementos de lista/tupla gerando lista nova</cyan>
  lista = [];
  for item in lst_tpl : lista.append(item);
  return lista;

lista = [1,2,[3]]; <cyan># define lista com 3 elementos, sendo o terceiro uma lista com 1 elemento</cyan>
aux = lista;
aux[2] = -1; <cyan># alterou lista[2]</cyan>
<verm>print</verm>("Lista: lista = %s" % lista);

lista = [1,2,[3]]; <cyan># lista</cyan>
<verm>print</verm>("Lista: lista = %s" % lista);
aux1 = copy.copy(lista); <cyan># copiar com funcao "copy(.)" de biblioteca "copy"</cyan>
aux2 = list(lista);      <cyan># copiar com gerar de lista "list(.)"</cyan>
aux3 = copiar(lista);    <cyan># copiar com funcao local "copiar(.)"</cyan>

aux1[2] = -1; <cyan># NAO alterou lista[2]</cyan>
aux2[2] = -1; <cyan># NAO alterou lista[2]</cyan>
aux3[2] = -1; <cyan># NAO alterou lista[2]</cyan>
<verm>print</verm>("aux1=%s, lista=%s" % (aux1, lista));
<verm>print</verm>("aux2=%s, lista=%s" % (aux2, lista));
<verm>print</verm>("aux3=%s, lista=%s" % (aux3, lista));

tupla = [1,2,[3]]; <cyan># tupla</cyan>
<verm>print</verm>("Tupla: tupla = %s" % tupla);
aux1 = copy.copy(tupla); <cyan># usar funcao 'copy' de biblioteca 'copy'</cyan>
aux2 = list(tupla);
aux3 = copiar(tupla);
<verm>print</verm>("aux1=%s, tupla=%s" % (aux1, tupla));
<verm>print</verm>("aux2=%s, tupla=%s" % (aux2, tupla));
<verm>print</verm>("aux3=%s, tupla=%s" % (aux3, tupla));</pre>
</div><!-- class="codigo" -->  

<p>
  Experimente! Esse código produz como saída as seguintes linhas:
<div class="exemplo"><i>Saídas do exemplo 3</i>.
</div><!-- class="exemplo" -->
<div class="codigo">
<pre>Lista: lista = [1, 2, -1]
Lista: lista = [1, 2, [3]]
aux1=[1, 2, -1], lista=[1, 2, [3]]
aux2=[1, 2, -1], lista=[1, 2, [3]]
aux3=[1, 2, -1], lista=[1, 2, [3]]
Tupla: tupla = [1, 2, [3]]
aux1=[1, 2, [3]], tupla=[1, 2, [3]]
aux2=[1, 2, [3]], tupla=[1, 2, [3]]
aux3=[1, 2, [3]], tupla=[1, 2, [3]]</pre>
</div><!-- class="codigo" -->   
</p>



<!-- secao -->
<a name="matriz">
<p class="secao">5. Defininido matriz como lista de lista</p>
</a>

<p>
  Uma vez que um vetor/lista é armazenado consecutivamente na memória, então podemos armazenar
  vários vetores também consecutivamente para obter algo que represente (e seja tratado como) <i>matriz</i>.
  Como na imagem abaixo, em que cada alocamos <i>nl</i> vetores consecutivos na memória, 
  cada vetor com <i>nc</i> posições de memória, desde <tt>vet[0]</tt> até <tt>vet[nc-1]</tt>.
  Assim, podemos ver este agregado de dados como uma matriz <tt>mat[][]</tt>, cuja primeira linha é
  o primeiro vetor e assim por diante. Isso está ilustrado na imagem abaixo.
  <center>
   <img src="img/int_vet_vet_representacao.png" title="representacao matriz e como fica em memoria como vetor de vetor"/>
  </center>   
</p>

<p>
  Desse modo obtemos uma estrutura com dois índices que pode ser manipulada como uma matriz (como em <i>mat[i][j]</i>).
  No exemplo abaixo ilustramos isso de dois modos, imprimindo as linhas da matriz
  e mostrando que pode-se passar como parâmetro uma linha de matriz para uma função que
  tenha como <i>parâmetro formal</i> um vetor.
</p>

<div class="exemplo"><i>Exemplo 3</i>. Construindo matriz como vetor de vetor e ilustrando que cada linha dela
  é um vetor, podendo portanto ser usado para chamar uma função que tem como parâmetro um vetor.
</div><!-- class="exemplo" -->
<div class="codigo">
  <pre><cyan># Vetor de vetor ou matriz</cyan>
# Definir vetor/lista com: (0,1,2,3,...n-1)
nl = 3; nc = 4;
mat = []; <cyan># define um vetor vazio</cyan>
for i in range(0, nl, 1) : <cyan># ou mais simples neste caso "for i in range(n)"</cyan>
  linha = []; <cyan># define um vetor vazio</cyan>
  for j in range(0, nc, 1) : <cyan># ou mais simples neste caso "for i in range(n)"</cyan>
    linha.append(i*n+j);
  mat.append(linha); <cyan># anexe nova linha `a matriz 'mat'</cyan>
# Imprime o vetor/lista de uma so' vez (na mesma linha)
<verm>print</verm>("\nA matriz: ", end=""); <cyan># informe o que vira impresso a seguir (na mesma linha devido ao parametro end=""</cyan>
<verm>print</verm>(mat);

# Pegando o primeiro e segundo elemento da terceira linha de mat: mat[2][1]
prim = mat[2][0]; seg = mat[2][1]; <cyan># pegar primeiro e segundo elemento da linha mat[2]</cyan>
<verm>print</verm>("O primeiro e segundo elemento da terceira linha da matriz: %d e %d" % (prim, seg));

<verm>print</verm>("Linhas da matriz: 0=%s ; 1=%s ; 2=%s" % (mat[0], mat[1], mat[2])); <cyan># cada linha e' um vetor!</cyan>
# <verm>print</verm>(mat[0]); <verm>print</verm>(mat[1]); <verm>print</verm>(mat[2]);

# Verifique que cada linha da matriz e' de fato um vetor
# Usar a funcao 'somalinha(...)' que soma elementos em vetor
for i in range(0, nl) :
  <verm>print</verm>("Soma da linha %2d = %3d" % (i, somalinha(mat[i])));</pre>
</div><!-- class="codigo" -->


<!-- secao -->
<a name="cuidados">
<p class="secao">6. Cuidados com referencias (ou apelidos)</p>
</a>

<p>
  Vocês devem tomar muito cuidado com atribuições envolvendo listas, pois na verdade <b style="color:#aa0000;">não</b> ocorre uma cópia,
  mas comentado na seção 4. Por exemplo, estude e teste em seu computador a sequência de comandos a seguir.
  <div class="codigo"><pre>>>> a = [1, 2, 3];
>>> b = a;
>>> b[2] = -9;
>>> print(a)
[1, 2, -9]</pre>
  <i>Cód. 1. Exemplo de uso de atribuição com listas, equivalente a referência, não cópia.  
  </div>
</p>

<p>
  Entretanto o <i>Python</i> oferece um mecanismo que efetivamente realiza uma cópia de cada um dos elementos, portanto
  envolve um <i>laço</i> de tamanho igual ao número de elementos da lista.
  Isso é feito usando algo como <tt>[inicio:fim]</tt>, sendo <i>inicio</i> a posição iniciar a partir da qual deseja copiar e
  <i>fim</i> o último elemento.
  <br/>Atenção ao <i>fim</i>, não é posição, mas sim número do elemento, então se <i>fim=3</i>, irá copia
  até o terceiro elemento. Por exemplo, algo como <tt>b = a[4:3];</tt> resultaria em lista vazia, pois o terceiro elemento está antes
  do elemento da posição <i>4</i>.
  <div class="codigo"><pre>>>> a = [0, "um", 2, 3, 4, 5, 6, 7, 8];
>>> v1 = a[4:3]; v2 = a[0:3]; print(v1, v2);
([], [0, 'um', 2])</pre>
  <i>Cód. 2. Exemplo truque para cópiar vários elementos.  
  </div>
</p>


  <p class="autoria">
    <a href="https://www.ime.usp.br/~leo" target="_blank" title="seguir para a pagina do prof. Leônidas">Leônidas de Oliveira Brandão</a><br/>
    <a href="http://www.ime.usp.br/~leo" target="_blank" title="seguir para a página do LInE">http://line.ime.usp.br</a>
  </p>

<p class="rodape">
  <b>Alterações</b>:<br/>
  2020/08/12: novo formato, pequenas revisões<br/>
  sexta, 08 May 2020, 21:00<br/>
  segunda, 03 May 2018, 16:00
</p>


</div>