Mais um pouco de Python ======================= Nessa aula vamos continuar a nossa revisão de Python e trabalhar um pouco com listas (tipo `list`), que é uma das principais estruturas nativas do Python. Tópicos ------- - listas (tipo `list`) em Python; - funções com listas; - funções mutadoras e não mutadoras; e - um pouco sobre strings. Introdução ---------- Uma lista é uma estrutura sequencial indexada que permite armazenar e manipular objetos de qualquer tipo. Para saber mais sobre listas recomendamos a leitura de `Lista: estrutura sequencial indexada `__. Para ilustrar o uso de listas vamos usar um programa que realiza a criação, carregamento e varrimento de uma lista em Python. Esse programa lê um inteiro ``n`` e uma sequência de ``n`` números, armazena-os em uma lista de tamanho ``n`` e imprime a sequência na ordem reversa a da leitura. Por exemplo, para ``n = 4`` e a sequência de números ``7, 5, 3, 1``, a saída do programa (o que o programa imprime) deve ser a sequência ``1, 3, 5, 7``. Para visualizar o funcionamento passo-a-passo de programas em Python vamos usar a ferramenta `Python Tutor `__. Essa é uma ferramenta grátis que se sustenta por meio de anúncios. Caso, durante a simulação, seu navegador redirecione para o site do Python Tutor, você pode redimensionar a janela para "esconder" os anúncios. A seta vermelha indica a próxima instrução a ser executada pelo Python. Clique no botão ``Next >`` até que a seta chegue ao final do arquivo, linha 22, que chama a função ``main()``. Continue clicando em ``Next >`` até chegar na linha 5, que cria a lista vazia ``seq``, que é uma estrutura dentro da função ``main()``. Observe que o Python Tutor atualiza o estado do programa após cada instrução, mostrando as variáveis e seus conteúdos. A linha 6 recebe um inteiro. O Python Tutor abre uma janelinha abaixo do código onde você pode digitar o valor desejado para ``n``, como, por exemplo, 4. Digite esse valor e clique em ``Submit``. Continue clicando em ``Next >`` e entrando com os valores desejados até o programa terminar. Observe também que a saída do programa, resultado dos comandos ``print``, aparecem em uma área no topo à direita da janela do Python Tutor. .. raw:: html .. ''' Lê uma sequência e imprime os valores em ordem reversa ''' def main(): seq = [] # cria uma lista vazia n = int(input("Digite o tamanho da sequencia: ")) for i in range(n): num = int(input(f"Digite o {i+1} inteiro da sequencia: ")) seq.append(num) # podemos imprimir a lista no print print("Lista de entrada: ", end=" ") print(seq) # vamos imprimir a lista em ordem reversa print("Lista reversa: ", end=" ") for i in range(n-1, -1, -1): print(seq[i], end = " ") print() # chama a função main() main() Nesse exemplo, utilizamos o comando `for (clique aqui para saber mais sobre o comando for) `__ para varrer as listas. Observe modificamos o parâmetro ``end`` da função ``print()`` para que os elementos da lista fossem impressos na mesma linha. Copie esse programa para o Spider para executá-lo usando outras sequências de entrada em seu computador. Teste o seu conhecimento: Soma de uma lista de números ...................................................... Escreva uma função que recebe uma lista com números e retorna a soma desses números usando o comando de repetição `while `__. .. raw:: html .. code:: Python def main(): ''' teste da funcao soma ''' teste1 = [] # lista vazia print("Soma de", teste1, "= ", soma_lista(teste1)) teste2 = [2] # print("Soma de", teste2, "= ", soma_lista(teste2)) teste3 = [1,2,3] print("Soma de", teste3, "= ", soma_lista(teste3)) teste4 = [0, -1, 7, 2, 5] print("Soma de", teste4, "= ", soma_lista(teste4)) def soma_lista(lista): ''' (list) -> int recebe uma lista de inteiros e retorna a soma ''' # ESCREVA A SUA FUNCAO return 0 main() .. Exercício 5: Máximo de uma lista de números ........................................... Escreva uma função que recebe uma lista com números e retorna o valor máximo desses números e o índice onde ele ocorre. .. code:: Python def main(): ''' teste da funcao maximo ''' # CRIE OS SEUS TESTES # def max_lista(lista): ''' (list) -> int, int recebe uma lista de inteiros e retorna o valor maximo da lista e o indice onde ele ocorre ''' # ESCREVA A SUA FUNCAO return 0, 0 main() .. admonition:: Números inteiros e reais em Python Se você nunca programou com Python antes, procure se lembrar que o Python foi criado tendo em mente produzir resultados que sejam "naturais" para seus usuários e usuárias. Assim, a divisão ``3 / 2``, apesar de dividir dois inteiros, resulta no valor ``1.5``. Para "forçar" um resultado inteiro em Python, use o operador ``//``, como em ``3 // 2``. Outra curiosidade do Python é que a representação de números inteiros pode incluir tantos dígitos quanto necessários, sem a restrição de, por exemplo, limitar ao intervalo possível de representar com 32 ou 64 bits. Como exemplo, use a função fatorial da aula passada para calcular o 100! e veja o que acontece. Mas lembre-se que isso não acontece para números reais. O Python, por ser uma linguagem interpretada, permite a construção de programas mais flexíveis com relação aos dados. Experimente usar, nesse exercício de somar os elementos de uma lista, as seguintes listas: * uma lista só com inteiros, como ``[1, 2, 3]``; * uma lista só com reais, como ``[4.5, 6.7, 8.9]``; * uma lista mista, com inteiros e reais, como ``[1, 2, 3.14]``. Você acha que esses resultados são naturais? Teste o seu conhecimento: função inverta() .......................................... Escreva uma função que recebe uma lista de elementos e retorna uma nova lista contendo os elementos em ordem reversa. .. raw:: html .. ''' A função main() testa a função inverta''' def main(): teste1 = [] # lista vazia print(f"Lista reversa de {teste1} => {inverta(teste1)}") teste2 = [2] # print(f"Lista reversa de {teste2} => {inverta(teste2)}") teste3 = [1,2,3] print(f"Lista reversa de {teste3} => {inverta(teste3)}") teste4 = [0, -1, 7, 2, 5] print(f"Lista reversa de {teste4} => {inverta(teste4)}") def inverta(lista): ''' (list) -> list recebe uma lista de elementos e cria e retorna uma nova lista com os elementos em ordem reversa. ''' # Escreva a sua função aqui print('vixe! ainda não fiz a função inverta()') return [] main() Função mutadora ----------------- Quando trabalhamos com estruturas de dados como listas, que podem ser muito muito grandes, é comum tentar "economizar" memória modificando a lista de entrada ao invés de criar uma nova. Vamos chamar essas funções de **mutadoras**, pois modificam a estrutura original. A função ``inverta()``, que você escreveu anteriormente, é **não mutadora**. Observe que a sua função ``inverta()`` retorna uma lista, enquanto a função ``inverta_mutadora()``, mostrada abaixo no Python Tutor, retorna ``None``. ``None`` é um objeto do Python que representa algo sem valor. Ela **deve** retornar ``None`` pois a própria lista de entrada é modificada. Estude o comportamento dessa função clicando no botão ``Next >``. .. raw:: html Um pouco sobre strings ---------------------- Uma string é uma sequência com um ou mais caracteres, ou seja, é um texto, que pode inclusive ser vazio. Uma string pode ser delimitada por aspas como ``"Um string"`` ou apóstrofes como ``'outra string'``. Essa flexibilidade permite colocar aspas ou apóstrofes nas strings, como ``"string com 'apóstrofes' entre apóstrofes."`` Essa sequência de caracteres se comporta como uma lista para acessar seus elementos e `fatias (intervalos de elementos) `__. Assim como listas, strings podem ser **concatenadas** usando o operador ``+``. O código a seguir ilustra como percorrer uma string pegando fatias de tamanho 10 e, ao final, concatenando as fatias em ordem reversa. Clique em `` Next > `` para executar o programa passo-a-passo. .. raw:: html A grande diferença com listas é que as strings são **imutáveis**. Assim, mesmo que você precise trocar apenas um caractere de uma string, de "gato" para "rato" por exemplo, o seguinte trecho de programa é inválido: .. code:: python animal = "gato" animal[0] = "r" print(animal) Nesse caso, é necessário criar uma nova string com o valor desejado. Clique `nesse link `__ para saber mais sobre strings. Exercícios ---------- #. Escreva uma função que recebe uma lista com números e, usando o comando ``for``, procura e retorna o valor mínimo desses números e o índice onde esse valor ocorre. Por exemplo, para a lista ``[5, 0, 7, -3, 9]``, o menor valor é ``-3`` que ocorre no índice 3. * Dica: em Python, para uma função retornar mais de um valor, basta separar os valores por vírgula. #. Escreva uma função que recebe uma lista com strings (palavras) e, usando o comando ``for``, procura a palavra de menor ordem alfabética e retorna a palavra e o índice onde ela ocorre. Por exemplo, para a lista ``["gato", "elefante", "cavalo", "formiga"]``, a "menor" palavra (em ordem alfabética) é "cavalo" que ocorre no índice 2 da lista. #. Escreva uma função que recebe uma string ``texto`` e retorna uma lista contendo as palavras do ``texto``. Uma palavra é uma sequência de caracteres separada por um ou mais caracteres da lista ``SEPARADORES = ["\n", "\t", " ", ",", ".", ";"]``. .. #. Escreva uma função que recebe uma string e retorna duas listas. .. Nos exercícios restantes dessa aula vamos usar números harmônicos para explorar vários conceitos. O número harmônico :math:`H_n` de ordem :math:`n`, :math:`n > 0`, é definido como a soma: .. math:: H_n = 1 + \cfrac{1}{2} + \cfrac{1}{3} + \cfrac{1}{4} + \ldots + \cfrac{1}{n} .. Vamos escrever duas funções que recebem :math:`n` e calculam e retornam o valor de :math:`H_n`: - ``harmonico_DE()``: calcula a soma da direita para a esquerda (= adicionando os termos de :math:`1/1` a :math:`1/n`, nessa ordem); e - ``harmonico_ED()``: calcula a soma da esquerda para a direita (= adicionando os termos de :math:`1/n` a :math:`1/1`, nessa ordem). A começar da função ``harmonico_ED()``, logo a seguir. Execute o trecho de código abaixo e veja o se resultado. .. code:: Python # exercicio_numero_harmonico_ED def harmonico_ED(n): ''' (int) -> float Recebe um numero inteiro positivo e retorna o numero harmonico de ordem n. O numero harmonico e calculado somando os termos da esquerda para a direita. ''' soma_ed = 0 for i in range (1, n+1): soma_ed += 1/i return soma_ed # testes print("Hed( 10) =", harmonico_ED(10)) print("Hed(15) =", harmonico_ED(15)) #. Escreva a função ``hTermos(n)`` que retorna uma lista com os termos da função harmônico ``H(n)`` de um inteiro ``n > 0``. Assim, a chamada ``hTermos(5)`` deve retornar a lista [1, 0.5, 0.333333, 0.25, 0.2]. #. Escreva um programa que leia um inteiro ``n > 0`` e imprima o valor de ``H(n)``, usando as funções ``hTermos(n)`` e ``soma_lista()``. #. Escreva um programa que leia um inteiro ``n > 0`` e imprima o valor de ``Hinv(n)``, que corresponde ao valor de ``H(n)`` calculada usando a lista de ``hTermos(n)`` em ordem reversa. .. admonition:: Dica Para esse exercício, utiliza a sua função ``inverta()`` para inverter a lista, mas sem modificar a lista de entrada. .. #. Devido a erros de quantização (já que os números reais representados no computador possuem precisão finita limitadas por, por exemplo, 64 bits), o valor de ``H(n)`` e ``Hinv(n)`` nem sempre serão iguais. Escreva um programa que varia ``n`` de 1 a 100 e imprima os valores de ``h`` e a diferença entre ``H(n)`` e ``Hinv(n)`` quando essa diferença for diferente de zero. Onde estamos e para onde vamos? ------------------------------- Continuando a nossa revisão de Python, vimos como manipular listas em Python. Lista é uma estrutura nativa do Python que permite reunir, de forma sequencial, vários elementos que podem ter tipos distintos. Vimos que funções mutadoras recebem listas e podem modificar seu conteúdo e vimos que strings são imutáveis. Na próxima aula, começar a introdução de conceitos de Programação Orientada a Objetos. Esses conceitos permitem abstrair outras estrutura de dados para que possamos focar no uso e não na representação dessas estruturas. Como exemplo de motivação, vamos utilizar o problema de cálculo de números harmônicos. Para saber mais --------------- Para saber mais sobre Python: * `Como Pensar como um Cientista da Computação - Aprendendo com Python: Edição interativa `__ que é uma tradução do livro `How to Think Like a Computer Scientist - Learning with Python: Interactive Edition `__. * `Estudo dirigido `__: aulas interativas do curso de Introdução à Computação em Python. * `Lista `__. * `Strings e Arquivos `__. .. aula presencial 02 * 20 minutos listas em Python * 80 minutos - .. #---------------------------------------------------- def busque_item( obj, lista ): '''(obj, list) -> int ou None Recebe uma lista, e retorna o índice da primeira ocorrência de obj na lista. Caso obj não ocorra na lista, a função retorna None. Sua função deve varrer a lista usando o comando for ou Exemplos: >>> busque_item( -3, [5, 0, 7, -3, 9] ) 3 >>> busque_item( 'cavalo', ["gato", "elefante", "cavalo", "formiga"] ) 2 >>> busque_item( 'cavalo', ["gato"]) None ''' # beginfora n = len(lista) for i in range(1,n): if lista[i] < menor_valor: menor_valor = lista[i] menor_indice = i return menor_valor, menor_indice # endfora def busque_menor( lista ): '''(list) -> (obj, int) ou (None, None) Recebe uma lista, e retorna a tupla formada pelo objeto de menor valor e o seu índice. Caso a lista seja vazia, retorna a tupla (None, None) Exemplos: >>> busque_menor( [5, 0, 7, -3, 9] ) (-3, 3) >>> busque_menor( ["gato", "elefante", "cavalo", "formiga"] ) ('cavalo', 2) >>> busque_menor([]) (None, None) ''' # beginfora if lista == []: return (None, None) menor_valor = lista[0] menor_indice = 0 n = len(lista) for i in range(1,n): if lista[i] < menor_valor: menor_valor = lista[i] menor_indice = i return menor_valor, menor_indice # endfora # COMPLETE ESSA FUNÇÃO E MUDE O CÓDIGO ABAIXO print("Vixe! ainda não fiz a função busque_menor()") return None, None