{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Continuando com números primos\n", "\n", "Vamos escrever uma função para calcular os n primeiro números primos." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def primeiros_primos_v0(n):\n", " # Começamos com uma lista vazia de primos conhecidos\n", " primos = []\n", " # O primeiro candidato é o 2\n", " candidato = 2\n", " while len(primos) < n: # Enquanto não tiver primos suficientes\n", " # insere candidato em primos se for primo\n", " eh_primo = True # Assume que candidato é primo até prova em contrário\n", " for p in primos: # Verifica todos os primos anteriores\n", " if candidato % p == 0:\n", " eh_primo = False # É divisível, portanto candidato não é primo\n", " break\n", " if eh_primo:\n", " # Se é primo, acresenta na lista\n", " primos.append(candidato)\n", " # Passa para o próximo candidato\n", " candidato += 1\n", " return primos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Agora vamos fazer uma outra variante da mesma função, usando a opção `else` do comando `for`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def primeiros_primos(n):\n", " # Começamos com lista vazia de candidatos\n", " primos = []\n", " # O primeiro candidato é o 2\n", " candidato = 2\n", " while len(primos) < n: # Enquanto não tiver primos suficientes\n", " # insere candidato em primos se for primo\n", " for p in primos: # Percorre todos os primos anteriores\n", " if candidato % p == 0:\n", " break # Se é divisível, interrompe loop\n", " else:\n", " # Se loop não foi interrompido, não é divisível por nenhum\n", " # primo anterior, portanto é primo.\n", " primos.append(candidato)\n", " # Passa para o próximo candidato. Vamos evitar os pares...\n", " if candidato == 2:\n", " candidato = 3\n", " else:\n", " candidato += 2\n", " return primos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alguns testes..." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primeiros_primos_v0(10)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primeiros_primos(10)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primeiros_primos(1)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primeiros_primos(0)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "primeiros_primos(-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Agora vamos definir uma função verificar se um número dado é primo. Para isso, vamos usar a função que calcula primos até um dado número, da aula anterior, que está copiada abaixo (corrigindo um pequeno problema, relacionado com a situação onde a lista de primos resultante é vazia)." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import math\n", "def primos_ate(n):\n", " # Primeiro formamos uma lista com os inteiros de 2 a n\n", " # Esses são os candidatos a primos.\n", " candidatos = list(range(2, n + 1))\n", " # Se a lista for vazia, já sabemos o resultado.\n", " if len(candidatos) == 0:\n", " return []\n", " # Ao calcular a raiz quadrada de n, arredondamos para cima, \n", " # para evitar problemas com aproximação numérica.\n", " raiz_n = int(math.ceil(math.sqrt(n)))\n", " # i mantém a posição do primo atual (que está limpando a lista)\n", " # corrente é o valor de candidatos[i]\n", " # começamos na posição inicial (que tem valor 2)\n", " i, corrente = 0, candidatos[0]\n", " while corrente <= raiz_n:\n", " # Os múltiplos de corrente são os que estão nas posições\n", " # j = i + k * corrente, k = 1, 2, ...\n", " j = i + corrente\n", " while j < len(candidatos):\n", " candidatos[j] = None # Marcamos os múltiplos com None\n", " j += corrente\n", " # Agora que eliminamos os múltiplos de corrente, vamos\n", " # avançar corrente (e i) para o próximo não eliminado\n", " j = i + 1\n", " while j < len(candidatos):\n", " # Se encontramos um candidato não eliminado saímos\n", " if candidatos[j] is not None: break\n", " # Senão, testamos o próximo\n", " j += 1\n", " else:\n", " # Se não houve break, não foi achado candidato.\n", " # Isso quer dizer que não há mais primos a testar.\n", " break\n", " # Se o código continua, então candidatos[j] é o próximo primo.\n", " i, corrente = j, candidatos[j]\n", " # Agora todos os que não estão marcados com None são primos.\n", " # Copio esses valores em uma lista de resultados.\n", " res = []\n", " for x in candidatos:\n", " if x is not None:\n", " res.append(x)\n", " return res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para saber se um número é primo, podemos testar sua divisibilidade por todos os primos menores ou iguais a sua raiz quadrada (pois pelo menos um de seus fatores primos tem que estar nessa faixa)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def eh_primo(n):\n", " # Calcularmos a raiz quadrada, usando a função round para pegar o\n", " # inteiro mais próximo\n", " raiz_n = round(math.sqrt(n))\n", " # Pegamos então uma lista com todos os inteiros até raiz_n\n", " primos = primos_ate(raiz_n)\n", " # Verificamos se algum desses primos divide n\n", " for p in primos:\n", " if n % p == 0:\n", " # n é divisível por p, portanto não é primo\n", " return False\n", " # n não é divisível por nenhum dos valores em primos,\n", " # portanto é primo.\n", " return True" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(True, True, False, False, True)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eh_primo(2), eh_primo(5), eh_primo(9), eh_primo(36), eh_primo(37)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eh_primo(1892832876219)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para terminar nossa exploração de número primos, vamos definir uma função que dá a decomposição de um número inteiro em fatores primos. Se um mesmo primo é múltiplo na decomposição, ele aparecerá com essa multiplicidade na lista de fatores. Por exemplo, para 24 devemos ter [2, 2, 2, 3]; para 17 teremos [17]." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def fatores_primos(n):\n", " # Começamos com uma lista vazia de fatores\n", " fatores = []\n", " # Calculamos a raiz quadrada de n\n", " raiz_n = round(math.sqrt(n))\n", " # Encontramos uma lista de primos até raiz_n\n", " primos = primos_ate(raiz_n)\n", " # Para cada um dos primos nessa lista, verificamos se ele é\n", " # fator de n (e quantas vezes)\n", " for primoatual in primos:\n", " # Enquanto n for divisível por primoatual, adicionamos\n", " # esse fator na lista de fatores e retiramos esse fator de n.\n", " # Note que se n não é divisível por primoatual, nada ocorre.\n", " while n % primoatual == 0:\n", " fatores.append(primoatual)\n", " # Temos que usar // aqui, para divisão inteira\n", " n //= primoatual\n", " # Por fim, após dividir por todos os primos menores ou iguais à\n", " # raiz quadrada, o fator que sobrar (se diferente de 1) é também\n", " # um fator primo (prove isso!).\n", " if n != 1:\n", " fatores.append(n)\n", " return fatores" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 7]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fatores_primos(14)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 2, 5, 5]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fatores_primos(100)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[3, 3]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fatores_primos(9)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[3, 283, 2229485131]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fatores_primos(1892832876219)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eh_primo(2229485131)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algumas funções úteis adicioais\n", "\n", "Em primeiro lugar, `abs` pode ser usado para encontrar o valor absoluto, adaptado para os diversos tipos de números." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs(2)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs(-2)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.00123" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs(-.00123)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "abs(3+4j)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`min` e `max` podem ser usados para achar o mínimo ou máximo, respectivamente, de diversos valores (adaptadas a diversos tipos)." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "min(2, 4, 5, 1, 8, 9)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(2, 4, 5, 1, 8, 9)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'agora'" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "min('agora', 'isso', 'é', 'estranho')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As funções também operam com listas:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "-2" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "min([1, 4, 6, 0, 10, -2, 6])" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max([1, 4, 6, 0, 10, -2, 6])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Números de ponto fixo\n", "\n", "O módulo `decimal` permite lidar com números de ponto fixo (quantidade fixa de casas decimais depois da vírgula)." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from decimal import Decimal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os valores podem ser fornecidos por strings." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = Decimal('1.34')" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": true }, "outputs": [], "source": [ "b = Decimal('2.45')" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('3.79')" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a + b" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('-1.11')" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a - b" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('3.2830')" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a * b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note como o número de casas decimais se adaptou de acordo com a necessidade (produto de dois números com 2 casas decimais cada gera um número com 4 casas decimais de precisão, incluindo o zero no final para garantir esse número de casas).\n", "\n", "No caso da divisão, a precisão do resultado pode depender dos valores fornecidos." ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('0.5469387755102040816326530612')" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a / b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No caso acima, o resultado foi truncado para 28 casas decimais, que é o default do tipo Decimal (esse valor pode ser ajustado, veja documentação do tipo)." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('2')" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal('2.4')/Decimal('1.2')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Além de permitir lidar com várias casas decimais, outra vantagem da classe é que os cálculos serão precisos dentro da representação decimal usada. Lembre-se do exemplo de erro de aproximação com número de ponto flutuante:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5.551115123125783e-17" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "0.1 + 0.1 + 0.1 - 0.3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Usando Decimal, o valores são precisos:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = Decimal('0.1')\n", "b = Decimal('0.3')" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('0.0')" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a + a + a - b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Existem também formas de criar valores Decimal a partir de inteiros ou números de ponto flutuante:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('2')" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal(2)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('0.5')" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal(0.5)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('2.29999999999999982236431605997495353221893310546875')" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal(2.3)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('0.1000000000000000055511151231257827021181583404541015625')" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal(0.1)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Decimal('0.299999999999999988897769753748434595763683319091796875')" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Decimal(0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## \"Compreensão\" de lista\n", "\n", "O Python tem uma forma abreviada de se criar objetos como listas, dicionários e conjuntos, denominado _list comprehension_.\n", "\n", "Suponhamos que você deseja uma lista com todos os pares entre 0 e 10 (inclusive).\n", "\n", "Você pode usar um loop para criar a lista:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pares = []\n", "for i in range(0, 11, 2):\n", " pares.append(i)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4, 6, 8, 10]" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pares" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Neste caso, que não envolve cálculos, na verdade basta converter a `range` usada no for para lista:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4, 6, 8, 10]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(range(0,11,2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mas vamos supor que o que você quer é uma lista com o quadrado dos pares entre 0 e 10 (inclusive).\n", "\n", "Novamente, um for resolve isso:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false }, "outputs": [], "source": [ "quapares = []\n", "for i in range(0, 11, 2):\n", " quapares.append(i * i)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, 4, 16, 36, 64, 100]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quapares" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No entanto, como os valores não são igualmente espaçados, não podemos usar o truque de converter uma `range` para uma lista.\n", "\n", "Para esses casos, usamos a sintaxe compreensão de lista:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, 4, 16, 36, 64, 100]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[i * i for i in range(0, 11, 2)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A sintaxe é `[ expressao for var in col ]` onde `col` é uma coleção de valores (que pode ser varrida por um `for`), `var` é um nome de variável e expressao é uma expressão (que em geral usa o valor de `var`). \n", "\n", "A lista será formada colocando em `var` cada um dos valores de `col`, calculando a expressao para esse valor e inserindo o resultado em uma lista.\n", "\n", "No exemplo acima, `i` recebe sucessivamente os pares de 0 a 10 (inclusive) e na lista são inseridos os correspondente valores do quadrado de `i`.\n", "\n", "Os colchetes em volta dizem que queremos formar uma lista. Se usarmos chaves, então queremos um conjunto:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "{0, 4, 16, 36, 64, 100}" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "{ i * i for i in range(0, 11, 2) }" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "É possível também termos mais do que um `for` para a geração da lista." ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[0, -1, -2, -3, 1, 0, -1, -2, 2, 1, 0, -1, 3, 2, 1, 0]" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[ i - j for i in range(0, 4) for j in range(0,4)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Neste caso, tanto i quanto j estão sendo variados de 0 a 3, com j variando mais rapidamente que i (isto é, para cada valor de i consideramos todos os valores de j, na ordem).\n", "\n", "Outra possibilidade é incluir um _filtro_, quer dizer, uma condição que será usada para testar se o valor deve ser inserido na lista ou não. Se a condição for verdadeira, o correspondente valor será inserido, senão ele será ignorado.\n", "\n", "Por exemplo, a lista abaixo tem os quadrados dos valores de i de 2 a 29, mas apenas se i for primo; isto é, ela tem os valores dos quadrados dos primos de 2 a 29." ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[4, 9, 25, 49, 121, 169, 289, 361, 529, 841]" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[i * i for i in range(2,30) if eh_primo(i)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mais algumas funções úteis\n", "\n", "Frequentemente, queremos operar em elementos de listas correspondentes (isto é, o primeiro elemento da primeira lista com o primeiro da segunda, o segundo da primeira com o segundo da segunda, etc.)\n", "\n", "Para isso, a forma mais fácil é usar a função `zip`, que percorre esses elementos retornando tuplas com os objetos correspondentes." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[(1, 3), (2, 4), (3, 5)]" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(zip([1,2,3], [3,4,5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso é especialmente útil em operações com `for`, tanto o normal como o de compreensões de lista." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[-3, -3, -3]" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[i - j for i,j in zip([1,2,3],[4,5,6])]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O código acima cria, com `zip`, uma coleção com os elementos (1,4), (2,5) e (3,6). Cada uma dessas tuplas é então, uma por vez, desempacotada colocando o primeiro elemento em `i` e o segundo em `j`. Esses valores de `i` e `j` são então usados na expressão `i-j` para formar a lista resultante.\n", "\n", "Se uma das listas for menor que a outra, o zip termina quando a menor termina." ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "([(10, 5), (20, 15)], [(5, 10), (15, 20)])" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = [10, 20, 30]\n", "b = [5, 15]\n", "list(zip(a,b)), list(zip(b,a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma outra função interessante é o `enumerate`, que permite percorrer uma lista verificando simultaneamente o índice e o valor de cada elemento (numa tupla)." ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": true }, "outputs": [], "source": [ "lista = [10, 11, 12, 13]" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[(0, 10), (1, 11), (2, 12), (3, 13)]" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(enumerate(lista))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso é bastante útil quando queremos varrer uma lista acessando tanto o valor dos seus elementos quanto o índice em um `for`:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A posição 0 tem valor 10\n", "A posição 1 tem valor 11\n", "A posição 2 tem valor 12\n", "A posição 3 tem valor 13\n" ] } ], "source": [ "for i, v in enumerate(lista):\n", " print('A posição', i, 'tem valor', v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algumas opções de leitura de arquivos\n", "\n", "Já vimos que é possível ler todo o conteúdo de um arquivo em uma única string usando o método `read`:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": true }, "outputs": [], "source": [ "f = open('teste.txt', 'r')\n", "conteudo = f.read()" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'Este é um teste.\\nSegunda linha\\n\\nEm cima foi um espaco.\\n\\n\\n\\n\\n\\nAcabou.\\n'" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "conteudo" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": true }, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso é um método bastante conveniente e funciona bem quando o arquivo não é muito grande. Para arquivos muito grandes, esse método ocupa muita memória, e pode ser mais adequado ler o arquivo aos pedaços.\n", "\n", "Uma forma de fazer isso é, ao chamar o método `read`, especificar o número de caracteres que queremos que sejam lidos. Neste caso, o método retorna uma sring com até esse número de caracteres, ou uma string vazia se o arquivo já acabou:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Es\n", "te\n", " é\n", " u\n", "m \n", "te\n", "st\n", "e.\n", "\n", "S\n", "eg\n", "un\n", "da\n", " l\n", "in\n", "ha\n", "\n", "\n", "\n", "Em\n", " c\n", "im\n", "a \n", "fo\n", "i \n", "um\n", " e\n", "sp\n", "ac\n", "o.\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ac\n", "ab\n", "ou\n", ".\n", "\n" ] } ], "source": [ "f = open('teste.txt')\n", "# Como não sabemos o tamanho do arquivo, usamos um loop infinito\n", "while True:\n", " c = f.read(2)\n", " # Interrompemos o loop se nada foi lido (fim do arquivo)\n", " if not c: break\n", " print(c)\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um outro método de leitura, mais conveniente para arquivos de texto, é o `readline` que lê uma linha por vez do arquivo:" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ESTE É UM TESTE.\n", "SEGUNDA LINHA\n", "\n", "EM CIMA FOI UM ESPACO.\n", "\n", "\n", "\n", "\n", "\n", "ACABOU.\n" ] } ], "source": [ "f = open('teste.txt')\n", "while True:\n", " linha = f.readline()\n", " if not linha: break\n", " # Só para variar, vamos limpar os espaços e converter para maiúsculas\n", " linha = linha.strip()\n", " print(linha.upper())\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Também podemos usar o `readlines`, que lê todo o arquivo de uma única vez mas, em contraste com o `read`, retorna uma lista com uma string para cada linha lida:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Este é um teste.\n", "Segunda linha\n", "\n", "Em cima foi um espaco.\n", "\n", "\n", "\n", "\n", "\n", "Acabou.\n" ] } ], "source": [ "f = open('teste.txt')\n", "for linha in f.readlines():\n", " print(linha.strip())\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nada impede de usar esses métodos dentro de uma compreensão de lista. Por exemplo, o código seguinte coloca numa lista apenas as linhas do arquivo `teste.txt` que contenham a subcadeia `me`:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['Este é um teste.\\n', 'Em cima foi um espaco.\\n']" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "arq = open('teste.txt')\n", "[linha for linha in arq.readlines() if linha.find('um') != -1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python [default]", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }