{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O Python é uma linguagem interpretada. Podemos fornecer comandos ao interpretador, que serão executados imediatamente (não existe uma fase de compilação)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 + 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1 Tipos de dados" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Existem três tipos numéricos primitivos em Python:\n", "- Inteiros\n", "- Números de ponto flutuante\n", "- Números complexos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1 Inteiro" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os números inteiros têm precisão ilimitada (podemos representar um número tão grande quanto o computador e o interpretador consigam)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "12" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "-12" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10000000000000000000000000000 - 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2 Ponto flutuante" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os números de ponto flutuante são sempre de precisão dupla (64 bits)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2.3e-5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "0.42" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "-12.760113" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ ".5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3 Complexo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Números complexos podem ser representados pela notação cartesiana, colocando um `j` após o valor da parte imaginária." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 + 3j" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "0.45 - 1.2e3j" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Também podemos usar a notação `complex(a, b)` para $a + i b$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "complex(5, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2 Operações" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O Python entende todos os operadores aritméticos tradicionais para todos os tipos numéricos acima. A exponenciação é representada por `**`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1 + 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1 - 4" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3 * 4" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 / 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como vemos acima, a divisão de números inteiros **resulta em um número de ponto flutuante**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 ** 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3.2 - 1.4" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3.2 - 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3.2 - (1 - 4J)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "13 / 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(1+2j)/(1-1j)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A divisão inteira pode ser conseguida pelo operador `//`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "13 // 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O resto da divisão inteira é calculado pelo operador `%`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "13 % 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A divisão inteira arredonda para baixo (isto é, para $-\\infty$):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "-13 // 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O resto é sempre compartível com a divisão `(a // b) * b + (a % b) == a`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "-13 % 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um outro jeito de entender a relação entre a divisão inteira e o resto é que o resto está sempre entre 0 e o divisor." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "13 // -3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "13 % -3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3 Condicionais" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Blocos de comandos são representados em Python pela quantidade de **espaço em branco** antes dos comandos do bloco.\n", "\n", "O comando condicional é representado por um `if` seguido da condição e de dois pontos, com os comandos a serem executados caso a condição seja verdadeira delimitados pela quantidade de espaço em branco." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if 2 < 3:\n", " print('Ufa, ainda bem!')\n", " print('Fiquei assustado por um tempo.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if 2 >= 3:\n", " print('O que está acontecendo aqui?')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Colocamos um bloco dentro de outro bloco aumentando a quantidade de espaço em branco." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 3\n", "if x > 0:\n", " print('Positivo')\n", " if x % 2 == 0:\n", " print('Par')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para indicar comando a executar caso a condição seja falsa, usamos o comando `else`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if 2 < 3:\n", " print('Tudo certo')\n", "else:\n", " print('Problemas')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outro comando associado com o if é o `elif` que indica uma outra condição a testar, *caso a condição anterior tenha sido falsa*." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 1\n", "if x < 0:\n", " print('Negativo')\n", "elif x > 0:\n", " print('Positivo')\n", "else:\n", " print('Nulo')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4 Repetição" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma repetição é indicada pelo comando `while`, que tem sintaxe similar à do `if`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n = 10\n", "while n > 0:\n", " print(n)\n", " n -= 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5 For" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ao contrário de C, onde o `for` é apenas uma outra forma de escrever um `while`, o `for` de Python tem uma semântica diferente. No `for` se especifica uma variável e uma sequência de valores (mais precisamente: um iterador). Cada um dos valores da sequência será atribuído (em ordem e um por vez) à variável, e então o bloco de comandos dentro do `for` será executado.\n", "\n", "Por exemplo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in [2, 3, 5, 7, 11, 13]:\n", " print(x, x**2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "trans = {'a': 'primeiro', 'b': 'segundo', 'c': 'terceiro'}\n", "for k in trans:\n", " print(k, trans[k])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note no resultado acima: *a ordem em que os elementos são percorrido é determinada pelo gerador da sequência*. No caso de listas, serão gerados os elementos na ordem em que eles se encontram na lista, mas em dicionários (mais sobre eles adiante) a ordem depende de como eles são armazenados internamente.\n", "\n", "Bastante útil com o `for` é a sequência `range`, que tem o formato\n", "\n", " range(inicio, final, passo)\n", "\n", "e gera um conjunto de valores igualmente espaçados. Aqui, `inicio` indica o primeiro valor a gerar, `final` indica o valor onde se para de gerar (esse valor **não será incluído entre os gerados**) e `passo` é a separação de um valor para o próximo. Podemos omitir `passo`, e seu valor será assumido como 1. Podemos adicionalmente omitir `inicio` e seu valor será assumido como 0.\n", "\n", "Veja os exemplos:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(2, 10, 2):\n", " print(i)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(2, 10):\n", " print(i)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(10):\n", " print(i)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(10, 2, -2):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarmente útil é o gerador `enumerate`, que percorre uma dada sequência e gera pares índice/valor para essa sequência (os pares são tuplas com dois elementos; mais sobre tuplas adiante).\n", "\n", "Veja o exemplo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "valores = [2, 3, 5, 7, 11, 13, 17, 19]\n", "for i, x in enumerate(valores):\n", " print(i, ': ', x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i, k in enumerate(trans):\n", " print(i, ':', k)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6 Variáveis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variáveis não precisam ser declaradas. Uma variável em Python passa a existir no momento em que atribuímos um valor a ela.\n", "\n", "Na verdade, a variável recebe uma *referência* a um *objeto* que tem o valor atribuido. Uma referência é similar a um ponteiro em C. Uma variável pode referenciar objetos de qualquer tipo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 12" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 2 + 5j" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7 Estruturas de dados" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Existem algumas estruturas de dados pré-definidas que são bastante úteis:\n", "- Listas\n", "- Dicionários\n", "- Conjuntos\n", "- Tuplas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.1 Listas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Listas são listas ligadas com diversos elementos armazenados sequencialmente, na qual podemos com facilidade inserir ou retirar elementos.\n", "\n", "A lista na verdade guarda referências para os objetos (da mesma forma que as variáveis).\n", "\n", "Representamos uma lista usando `[` e `]` com os elementos separados por vírgulas." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares = [0, 2, 4, 6, 8, 10]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma lista pode ser indexada (o primeiro índice é zero) para acessar um elemento arbitrário." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O índice fornecido é verificado: Se ele for inválido, um erro será gerado, interrompendo a execução do programa." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[6]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos descobrir o número de elementos na lista com a função `len`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(primeiros_pares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Índices para as listas podem ser negativos. Neste caso, eles contam de trás para frente a partir do último elemento (o último é o índice -1)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Índices negativos também são verificados." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares[-7]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se quisermos encontrar índice de um elemento numa lista que tenha um valor especificado, podemos usar o método `index`, com a sintaxe abaixo (lista seguida de ponto seguida do nome do métodos seguido dos argumentos entre parêntesis)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares.index(8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se o elemento procurado não existe, o método `index` gera um erro (exceção)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares.index(12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos também acrescentar novos elementos no final das listas, usando o método `append`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares.append(12)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_pares.index(12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.2 Dicionários" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outra estrutura de dados é o chamado dicionário. Ele é uma estrutura que guarda pares chave/valor, associando um valor para cada chave fornecida. Chaves e valores podem ser qualquer objeto. Podemos depois consultar o dicionário para encontrar o valor associado a uma chave.\n", "\n", "A sintaxe é com `{` e `}` e pares chave/valor separados por vírgula; cada par chave/valor é representado pela chave, um \"dois pontos\" e o valor." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones = {\"ana\": 123, \"beto\": 456, \"carlos\": 789, \"bento\": 543}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para encontra o valor associado com uma chave usamos a sintaxe de indexação." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['beto']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos também mudar o valor associado a uma chave através dessa sintaxe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['carlos'] = 333" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As chaves são verificadas: se uma chave for solicitada para a qual nenhum valor foi fornecido, será gerado um erro." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['pedro']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por outro lado, podemos fornecer o valor para uma nova chave." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['pedro'] = 7777" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os valores são de tipos arbitrários. Por exemplo, o comando seguinte associa uma lista à chave `'ana'`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['ana'] = [123, 422]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['ana']" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "telefones['ana'][1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.3 Conjuntos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conjuntos são uma simplificação de dicionários que têm apenas chaves (sem valor associado). A vantagem dos conjuntos é que eles têm apenas uma cópia de cada elemento que for colocado neles." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_primos = {2, 3, 5, 7, 11, 13}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_inteiros = {0, 1, 2, 3, 4, 5}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos fazer algumas operações de conjuntos. Por exemplo, verificar se um elementos pertence a um conjunto:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "9 in primeiros_primos" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "4 in primeiros_inteiros" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou fazer a interseção de dois comjuntos." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_primos & primeiros_inteiros" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou a união de conjuntos." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_primos | primeiros_inteiros" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou a diferença de conjuntos." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_inteiros - primeiros_primos" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_primos - primeiros_inteiros" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou verificar se um conjunto é subconjunto de outro (`<` é usado para representar a relação de subconjunto)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_primos < primeiros_inteiros" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "{1, 2} < primeiros_inteiros" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "primeiros_inteiros > {1, 2}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se transformamos uma lista em conjunto, todos os valores duplicados são eliminados:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "alguns = [1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5]\n", "unicos = set(alguns)\n", "print(alguns, unicos, sep='\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso pode ser usado para eliminar duplicados de uma lista:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "so_alguns = list(set(alguns))\n", "so_alguns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.4 Tuplas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por fim, tuplas são sequências de valores de um tamanho fixo. Exemplos de tuplas são duplas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lados = (5, 7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou triplas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "triangulo = (3, 4, 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os elementos das tuplas podem ser acessados por indexação:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lados[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mas, contrariamente a listas, não podemos alterar os elementos referenciados pelas tuplas. Dizemos que as tuplas são **imutáveis**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lados[0] = 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8 Funções" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Novas funções podem ser definidas usando o comando `def`, seguido do nome da função e da lista de argumentos. Os argumentos, como tradicional em Python, não precisam indicar seus tipos.\n", "\n", "A função executa até terminar o bloco ou encontrar um `return`. O `return` especifica o valor a ser retornado pela função." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def poli_1(x):\n", " return 2*x**2 - 5 * x + 8" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poli_1(2.5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def contagem(n):\n", " while n > 0:\n", " print(n)\n", " n -= 1\n", " print('Acabou')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "contagem(5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def H(n):\n", " s = 0.0\n", " for i in range(1, n+1):\n", " s += 1 / i\n", " return s" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "H(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "H(1000)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "H(1000000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 9 Cadeias de caracteres" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cadeias de caracteres podem ser criadas delimitadas por `\"` ou `'`. Tanto faz o delimitador usado, desde que o usado para o fechamento seja o mesmo usado para a abertura." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome = 'Sistemas Complexos'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "codigo = \"7600054\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "potus = 'Donald \"Twitter Troll\" Trump'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(potus)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Também podemos especificar cadeias de caracteres que ocupam múltiplas linhas usando `\"\"\"` ou `'''` como delimitador:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "grande = \"\"\"\n", "Esta é uma cadeia que ocupa\n", "mais do que\n", "\n", "uma linha.\n", "\n", "\"\"\"\n", "outra = '''\n", "=======================\n", "Esta também\n", " ocupa \"múltiplas\"\n", "\n", "'linhas'\n", "\n", "\n", "'''\n", "print(grande)\n", "print(outra)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cadeias podem ser indexadas da mesma forma que listas." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outra forma de indexar (também válida em listas) é através de *slices*. Um slice é representado por\n", "\n", " inicio:final:passo\n", "\n", "e indica um conjunto de índices, com significado similar ao de `range`. Podemos omitir qualquer dos três elementos. Se `passo` é omitido, ele é assumido 1. se `inicio` é omitido, é assumido 0 e se `final` é omitido, é assumido que pegamos tudo até o final da cadeia." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[0:8]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[:8]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[9:]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nome[-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A indexação é por caracteres UTF-8 (o padrão no Python), e não por bytes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado = 'Computação Científica'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[6]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[7]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[8]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[9]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[3:-3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "acentuado[3:-3:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O número de caracteres em uma cadeia pode ser encontrado com a função `len`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(len(acentuado))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos converter uma cadeia de caracteres para um valor numérico, desde que ela seja válida:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = int(\"42\")\n", "f = float(\"42\")\n", "g = float(\"-3.573e-10\")\n", "c = complex(\"42\")\n", "z = complex(\"3+2j\")\n", "print(i, f, g, c, z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Essas operações podem também ser usadas para conversões entre tipos numéricos:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(float(2), int(3.7), complex(9.1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um método útil de cadeias de caracteres é o método `strip`, que elimina todos os espaços em branco no começo e no final de uma cadeia. Temos também o `rstrip` que limpa apenas o final e o `lstrip` que limpa apenas o começo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha = ' Primeiro 10 143.2 '" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.strip()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.rstrip()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.lstrip()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como se percebe acima, os métodos devolvem uma nova cadeia, deixando a cadeia original intacta.\n", "\n", "Outro método útil é o `split`, que permite quebrar a cadeia em uma lista de subcadeias de acordo com um separador. Se o separador não é especificado, separa-se por espaços em branco (espaços consecutivos são considerados um separador, e mudanças de linha e tabulações contam como espaços)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.split()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.split('10')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "linha.split(' ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A operação oposta ao `split` é feita pelo método `join`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "palavras = linha.split()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "palavras" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "' '.join(palavras)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "', '.join(palavras)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10 Arquivos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arquivos podem ser abertos para leitura pela função `open`. Após isso, podemos ler seu conteúdo usando diversos métodos, como o `read` (que lê todo o arquivo como uma cadeia única) ou o `readlines` que lê uma linha por vêz como uma cadeia, retornando uma sequência com todas as linhas.\n", "\n", "Quando não precisamos mais do arquivo, devemos fechá-lo com o método `close`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "arq = open('teste.txt')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tudo = arq.read()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tudo" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "arq.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quando usamos `open` com apenas o nome do arquivo, como acima, o arquivo é aberto para leitura, pois essa chamada é equivalente a especificar um segundo parâmetro `'r'`, como abaixo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "arq = open('teste.txt', 'r')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for linha_arq in arq.readlines():\n", " print('Esta é a linha:', linha_arq)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "arq.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Na verdade, o uso explícito de `close` não é recomendado em diversos casos, devido a possíveis problemas com situações de erro. A forma recomendada de lidar com arquivos (entre outros casos similares) é através do uso do comando `with`, como no código abaixo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('teste.txt') as arq:\n", " for i, linha_arq in enumerate(arq.readlines()):\n", " print('Esta é a linha', i, '=>', linha_arq)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O `with` faz a atribuição do valor retornado pelo `open` para a variável especificada depois do `as` e se responsabiliza por fazer o `close` quando a execução sai do seu bloco (não importa por qual caminho, mesmo que seja por um erro)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para abrir um arquivo para escrita, basta usar `'w'` ao invés de `'r'`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('saida.txt', 'w') as arq:\n", " print('Olá, caro novo usuário', file=arq)\n", " print('Seja bem vindo', file=arq)\n", " print('3 elevado a 27 vale', 3 ** 27, file=arq)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 11 Módulos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Muitas das funcionalidades de Python são fornecidas através de módulos, que são coleções de funções, classes e objetos que podem ser utilizados pelo programador. Por exemplo, para interface com o sistema operacional (`sys`); para dias e horas (`datetime`); operações matemáticas em ponto flutuante (`math`), entre inúmeros outros. Para usar as funcionalidades fornecidas por esses módulos, precisamos importá-los:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math # Impora tudo o que o módulo math define\n", "pi = 4 * math.atan(1) # math.atan é uma função que calcula arco-tangente\n", "print(pi)\n", "print('Isso o Python já sabia:', math.pi) # math.pi é uma constante" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outra opção, ao invés de importar o módulo, é importar identificadores específicos do módulo. Isso pode ser feito com `import ... from ...`, e neste caso não precisamos usar o nome do módulo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from math import sin\n", "print(sin(pi / 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 12 Alguns brindes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ao construir uma lista com valores desejados, temos várias opções. Uma delas é fornecer os valores manualmente." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pares_menores_que_20 = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n", "print(pares_menores_que_20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Outra é calcular os valores e colocá-los numa lista:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pares_menores_que_20 = []\n", "corrente = 0\n", "while corrente < 20:\n", " pares_menores_que_20.append(corrente)\n", " corrente += 2\n", "print(pares_menores_que_20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nesses casos simples, onde as repetições do loop são regulares, é sempre melhor usar um `for`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pares_menores_que_20 = []\n", "for corrente in range(0, 20, 2):\n", " pares_menores_que_20.append(corrente)\n", "print(pares_menores_que_20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Na verdade, vemos que os valores inseridos na lista são simplesmente os valores gerados pela `range`. Então, basta converter a range para uma lista:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pares_menores_que_20 = list(range(0, 20, 2))\n", "print(pares_menores_que_20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma outra forma de gerar listas diretamente é através da chamada *list comprehension*:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pares_menores_que_20 = [i for i in range(0, 20, 2)]\n", "print(pares_menores_que_20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A sintaxe inclui uma expressão para o cálculo do valor a ser inserido na lista (no exemplo apenas o valor da variável `i`), a palavra-chave `for` o nome da variável usada na expressão (no exemplo `i`) e a palavra-chave `in` seguida de um gerador de valores (no exemplo o `range`).\n", "\n", "É claro que para esse caso simples, é mais fácil usar a conversão direto da range para uma lista, como no exemplo acima, mas quando os cálculos são mais complexos, o uso de *list comprehension* fica interessante:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "potencia_2_de_alguns_pares = [2 ** i for i in range(0, 20, 2)]\n", "print(potencia_2_de_alguns_pares)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos usar sintaxes similares para gerar conjuntos ou dicionários:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "pares_ate_20 = {i for i in range(0, 20, 2)} # O mesmo que set(range(0, 20, 2))\n", "impares_ate_20 = {i for i in range(1, 20, 2)} # O mesmo que set(range(1, 20, 2))\n", "print('Pares:', pares_ate_20)\n", "print('Impares:', impares_ate_20)\n", "print('Todos:', pares_ate_20 | impares_ate_20) # O operador | é a união de conjuntos\n", "\n", "tabela_quadrados = {i: i**2 for i in range(10)}\n", "print('Tabela de quadrados:', tabela_quadrados)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Também podemos usar compreensões para gerar sequências (iteradores) de valores, que depois podem ser percorridads de acordo com o necessário. Para isso usamos `( )`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i, isquare in enumerate(i * i for i in range(10)):\n", " print(i, isquare)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note como os parêntesis da função enumerate já servem de parêntesis para a compreensão." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quando precisamos uma função simples (apenas um cálculo retornando um valor), não precisamos definir a função através de um `def`, mas podemos usar funções *lambda*, como abaixo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "meu_poli = lambda x: 2 * x**2 - 3*x + 5\n", "\n", "for i in range(7):\n", " print(meu_poli(i))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Essas funções podem usar não apenas constantes e os parâmetros, como no exemplo acima, mas também outros elementos definidos no contexto em que elas são criadas." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = 9.82\n", "tmax = lambda v0: v0/g\n", "\n", "print('Na Terra, para', 10, 'm/s, volta em', 2*tmax(10), 's')\n", "\n", "g = 1.624\n", "print('Mas na Lua, para', 10, 'm/s, volta em', 2*tmax(10), 's')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note como isso é muito perigoso e pode gerar dificuldades de interpretar resultados!** No caso acima, o ideal é que `g` seja também um parâmetro." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Algumas funções interessantes adicionais:\n", "\n", "- `abs(x)`: valor absoluto de `x`.\n", "- `all(it)`: retorna `True` se todos os valores em `it` forem `True` (ou equivalentes) ou se `it` for vazio.\n", "- `any(it)`: retorna `True` se qualquer dos elementos de `it` for `True`.\n", "- `chr(x)`: retorna caracter correspondente ao código inteiro `x`.\n", "- `input(st)`: Mostra mensagem `st`, aguarda cadeia de caracteres fornecida pelo usuário e a retorna.\n", "- `map(f, it)`: aplica a função `f` a cada um dos valores retornados pelo iterador `it` e retorna um iterador com os valores correspondentes.\n", "- `max(it)`: retorna o maior valor da sequência definida por `it`.\n", "- `min(it)`: retorna o menor valor da sequência definida por `it`.\n", "- `ord(c)`: retorna inteiro correspondente a código Unicode do caracter `c`.\n", "- `pow(x, y)`: equivalente a `x ** y` (mais adequado em algumas situações).\n", "- `reversed(it)`: fornece os valores da sequência definida por `it` em ordem revertida.\n", "- `round(x, n)`: arredonda `x` para `n` dígitos depois da vírgula. Se `n` não é fornecido, ele é assumido 0.\n", "- `sorted(it)`: fornece os valores da sequência definida por `it` em ordem crescente (ver também outros parâmetros na documentação).\n", "- `sum(it)`: retorna a soma dos valores da sequência definida por `it`.\n", "- `zip(it1, it2)`: retorna pares com um elementos de `it1` e um elementos de `it2`, até um dos iteradores terminar.\n", "\n", "Veja exemplos abaixo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x, y, z = 2, -3.4, 3 + 4j\n", "print('1:', abs(x), abs(y), abs(z))\n", "\n", "meus_valores = [1, 3, 5, 2, 4, 6, -7, -3, 0]\n", "print('2:', all(meus_valores), any(meus_valores), all(meus_valores[:8]))\n", "\n", "print('3:', min(meus_valores), max(meus_valores))\n", "\n", "print('4:', sum(meus_valores))\n", "\n", "print('5:', list(reversed(meus_valores)), list(sorted(meus_valores)))\n", "\n", "print('6:', list(map(lambda x: 3*x + 2, meus_valores)))\n", "\n", "ic = ord('c')\n", "x = chr(ic + 2)\n", "print('7:', ic, x)\n", "\n", "nome = input('Qual seu nome?')\n", "print('8:', 'Bem vindo, '+ nome+'!')\n", "print('9:', ''.join(map(lambda c: chr(ord(c) + 1), nome)))\n", "\n", "meu_pi = 3.14159265\n", "print('10:', meu_pi, round(meu_pi), round(meu_pi, 2), round(meu_pi, 4), round(meu_pi, 6))\n", "\n", "print('11:', end=' ')\n", "for a, b in zip(meus_valores, reversed(meus_valores)):\n", " print(a, ':', b, sep='', end=', ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 13 CUIDADO: Referências!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tanto variáveis como listas, tuplas e dicionários (além de outras estruturas de dados), guardam **referências** para objetos que têm os valores especificados. Lembre-se disso, para poder entender corretamente o funcionamento de codigos Python." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [1, 2, 3] # a é uma referência para essa lista alegre\n", "b = a # b é o mesmo que a, quer dizer, uma referência para a mesma lista. O objeto de lista é o mesmo!\n", "b[2] = 4 # Mudando o elementos de índice 2 da lista referenciada por b\n", "print('b vale:', b) # Veja o que é mostrado\n", "print('a vale:', a) # E aqui!!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso acontece pois, como escrito nos comentários, ao alterarmos `b[2]` estamos alterando o elemento de índice 2 da lista **referenciada** por `b`, que por acaso é a mesma lista referenciada por `a`. Isso vai acontecer com qualquer operação que altere a lista." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append(8)\n", "print('a vale:', a)\n", "print('b vale:', b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mas se mudarmos a referência de uma das variáveis, então elas não são mais relacionadas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b = [3, 4]\n", "print(a, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No caso acima, a primeira atribuição faz a variável `b` referenciar a nova lista (com os valores 3 e 4), e portanto deixar de referenciar a lista anterior. Mas a variável `a` não foi afetada, e continua referenciando a lista antiga." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou veja este caso um pouco mais elaborado:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def valor_absoluto(lista_original):\n", " lista_nova = lista_original\n", " for i, x in enumerate(lista_nova):\n", " lista_nova[i] = abs(x)\n", " return lista_nova\n", "\n", "minha_lista = [0, 1, -2, 3, -4, -5, 6, 7, -8]\n", "print('Lista antes de chamar a função:', minha_lista)\n", "sem_negativo = valor_absoluto(minha_lista)\n", "print('Aqui nenhum negativo:', sem_negativo)\n", "print('E esta é a original:', minha_lista)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para evitar alterar a lista original neste caso basta criar uma nova:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def valor_absoluto(lista_original):\n", " lista_nova = []\n", " for i, x in enumerate(lista_original):\n", " lista_nova.append(abs(x))\n", " return lista_nova\n", "\n", "minha_lista = [0, 1, -2, 3, -4, -5, 6, 7, -8]\n", "print('Lista antes de chamar a função:', minha_lista)\n", "sem_negativo = valor_absoluto(minha_lista)\n", "print('Aqui nenhum negativo:', sem_negativo)\n", "print('E esta é a original:', minha_lista)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou de forma mais simples, usando compreeensão de lista:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def valor_absoluto(lista_original):\n", " return [abs(x) for x in lista_original]\n", "\n", "minha_lista = [0, 1, -2, 3, -4, -5, 6, 7, -8]\n", "print('Lista antes de chamar a função:', minha_lista)\n", "sem_negativo = valor_absoluto(minha_lista)\n", "print('Aqui nenhum negativo:', sem_negativo)\n", "print('E esta é a original:', minha_lista)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No código abaixo, está uma tentativa de implementar um algoritmo que requer a iteração de valores em uma lista até que entre o valor atual e o anterior não haja uma diferença absoluta maior do que 0.0001.\n", "\n", "Veja o resultado. Você consegue explicar o que ocorreu?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "valores = [10., 3., 4., 7., 2., 8., 1., 0.5, 5., 0]\n", "N = len(valores)\n", "diff = 1.0\n", "passos = 0\n", "while diff > 0.0001:\n", " valores_antigos = valores\n", " for i in range(1, N-1):\n", " valores[i] = (valores_antigos[i-1] + 2.0 * valores_antigos[i] + valores_antigos[i+1]) / 4.\n", " diff = max(abs(valores_antigos[i] - valores[i]) for i in range(N))\n", " passos += 1\n", "\n", "print('Convergiu para os seguintes valores:', valores)\n", "print('Máxima diferença encontrada:', diff)\n", "print('Número de passos:', passos)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para resolver esse tipo de problema, precisamos garantir que a outra variável receba uma **referência para um novo objeto**, que então pode ter seu valor alterado sem alterar o objeto original. Para isso, usamos o método `copy`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [1, 2, 3]\n", "b = a.copy()\n", "b[2] = 4\n", "print('a vale', a)\n", "print('b vale', b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mas **cuidado**! Isso nem sempre é suficiente. Mais especificamente, o `copy` faz uma cópia do objeto, mas se esse objeto contém referências, ele simplesmente copia as referência..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = [[1, 2], [2, 4], [3, 6]]\n", "d = c.copy()\n", "d[0][1] = 314\n", "d.append(1234)\n", "print('c vale', c)\n", "print('d vale', d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Isso porque `d[0]` é uma referência para uma lista, que por acaso é a mesma referenciada por `c[0]`. Portanto, ao alterarmos `d[0][1]` estamos também alterando `c[0][1]`!\n", "\n", "Para esses casos, a saída geral (apesar de que podem haver soluções mais eficientes para cada problema específico) é usar a função `deepcopy` do módulo `copy`, que faz recursivamente uma cópia sempre que acha uma referência. Neste caso, como ele sabe que cada `c[i]` é uma referência, ele faz cópias de cada uma dessas listas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import copy\n", "c = [[1, 2], [2, 4], [3, 6]]\n", "d = copy.deepcopy(c)\n", "d[0][1] = 314\n", "print('c vale', c)\n", "print('d vale', d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Só isso por hoje! 😃" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercícios" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete o código abaixo para que ele imprima, para cada número de `minha_lista` \"par\" se o número for par e \"ímpar\" se o número for ímpar.\n", "\n", "A saída esperada é:\n", "```\n", "par\n", "par\n", "ímpar\n", "par\n", "ímpar\n", "ímpar\n", "ímpar\n", "par\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "minha_lista = [8, -2, 3, 104, -1, 701, 53, 100000]\n", "# Completar o código aqui" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete o código abaixo para que ele imprima os valores de produtos de todos os elementos da lista `a` com todos os elementos da lista `b`, da seguinte forma: Começando pelo primero elemento da lista `a`, listamos o produto dele com todos os elementos da lista `b`, na ordem em que eles aparecem em `b`, todos na mesma linha e separados por um espaço em branco; em seguida mudamos de linha e passamos para o próximo elemento de `a`, e assim por diante.\n", "\n", "O resultado esperado é:\n", "```\n", "20 60 80 40 \n", "40 120 160 80 \n", "30 90 120 60 \n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [2, 4, 3]\n", "b = [10, 30, 40, 20]\n", "# Completar o código aqui" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Refaça o exemplo anterior, mas com os elementos de `b` sendo percorridos em ordem reversa (do último para o primeiro).\n", "\n", "Saída esperada:\n", "```\n", "40 80 60 20 \n", "80 160 120 40 \n", "60 120 90 30 \n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [2, 4, 3]\n", "b = [10, 30, 40, 20]\n", "# Completar o código aqui" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete o código da função abaixo que deve retornar o menor e o maior (nessa ordem) elementos da lista **em valor absoluto** (mas o valor original deve ser retornado, isto é, se por exemplo o número com maior valor absoluto for negativo, é esse negativo que deve ser retornado, e não o seu valor absoluto.\n", "\n", "Teste o seu código com os teste abaixo." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def absminmax(lista):\n", " pass # Substituir este pass pelo seu código" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Testes:\n", "assert absminmax([1, 2, 3, 4]) == (1, 4)\n", "assert absminmax([4, 3, 2, 1]) == (1, 4)\n", "assert absminmax([1, 4, 2, 3]) == (1, 4)\n", "assert absminmax([-1, -2, -3, -4]) == (-1, -4)\n", "assert absminmax([-1, 2, -3, 4]) == (-1, 4)\n", "assert absminmax([1, -2, -3, 4]) == (1, 4)\n", "assert absminmax([3, 3, 3]) == (3, 3)\n", "assert absminmax([3, 3]) == (3, 3)\n", "assert absminmax([-3]) == (-3, -3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.4" } }, "nbformat": 4, "nbformat_minor": 4 }