123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- <!--
- 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> |
- <a href="#memoria" title=""></a>
- ]</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> </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> </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 <ENTER></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> </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/>
- <verm>print</verm>("%2d | %4.1f" % (i,vetor[i]));</td><td> </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/>
- <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/>
- <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>
|