{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "latter-fluid",
   "metadata": {},
   "source": [
    "# Aula 05: Funções\n",
    "\n",
    "Esta aula é baseada no capítulo 8 do livro \"Introdução à programação com Python. Algoritmos e lógica de programação para iniciantes\" de Nilo Ney Coutinho Menezes.\n",
    "\n",
    "Esta é talvez a aula mais importante do curso.\n",
    "\n",
    "Começamos o curso usando o interpretador (terminal do python na verdade) como uma calculadora. Nessa calculadora incrementada, aprendemos a trabalhar com números (inteiros e de ponto flutuante) e também com strings. \n",
    "\n",
    "<!-- TEASER_END -->\n",
    "\n",
    "Logo no começo introduzimos um primeiro mecanismo de abstração: variáveis. Com as variáveis, pudemos dar nomes a valores. Aí bastava mudar o valor e executar o programa novamente.\n",
    "\n",
    "Mas só variáveis não permitem que a gente faça muita coisa. Então aprendemos a usar expressões condicionais. Com isso e variáveis podíamos escolher que parte do programa seria executado. \n",
    "\n",
    "Mas ainda assim, estávamos bem limitados ao que podíamos fazer. Então introduzimos algumas estruturas de dados mais complexas como \n",
    "\n",
    " * Listas\n",
    " * Dicionários\n",
    " * Tuplas\n",
    " * Conjuntos\n",
    "\n",
    "Com isso começamos a implementar programas mais sofisticados, desenvolvendo algoritmos mais complexos (como por exemplo o programa para reordenar listas) e até mesmo joguinhos.\n",
    "\n",
    "Mas ainda assim temos um problema: como reaproveitar programas ou parte dos programas? Ou executamos o programa novamente ou fazemos um *copy and paste*. \n",
    "\n",
    "Aqui que entra o conceito de funções!\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "joint-column",
   "metadata": {},
   "source": [
    "## O que são funções em Python?\n",
    "\n",
    "O termo surge da semelhança com as funções em matemática como por exemplo a função seno ou cosseno. \n",
    "\n",
    "$$\n",
    "y = cos(x)\n",
    "$$\n",
    "\n",
    "Dado um valor representado por x, a função `cos` returna um outro valor que corresponde ao cosseno do valor x.\n",
    "\n",
    "Em Python, a função cosseno é implementada no módulo `math` que deve ser carregado:\n",
    "```python\n",
    "import math\n",
    "```\n",
    "e agora podemos usar acessar a função que calcula o cosseno como \n",
    "```python-repl\n",
    "In [1]: import math\n",
    "\n",
    "In [2]: print(math.cos(0.5))\n",
    "0.8775825618903728\n",
    "```\n",
    "\n",
    "Muitas vezes é inconveniente ficar digitando `math.cos(0.5)` então podemos fazer\n",
    "\n",
    "```python-repl\n",
    "In [5]: from math import cos\n",
    "\n",
    "In [6]: print(cos(0.5))\n",
    "0.8775825618903728\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "hollywood-typing",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "tracked-handling",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8775825618903728"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.cos(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "deadly-mount",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.479425538604203"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.sin(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "worst-sample",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5463024898437905"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.tan(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "brazilian-helmet",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5463024898437905"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.sin(0.5) / math.cos(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "prescribed-genre",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.sin(0.5)**2 + math.cos(0.5)**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "suspended-premiere",
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import cos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "portable-miller",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8775825618903728"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cos(0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sacred-dating",
   "metadata": {},
   "source": [
    "A biblioteca padrão do Python implementa um monte de coisa útil para o programador. Dê uma olhada na página <https://docs.python.org/pt-br/3/library/index.html>.\n",
    "\n",
    "O módulo `math` tem um monte de coisa interessante <https://docs.python.org/pt-br/3/library/math.html>\n",
    "\n",
    "\n",
    "Mas agora, o que queremos fazer é aprender a criar as nossas próprias funções.\n",
    "\n",
    "Vamos começar com algo bem simples (e inútil!). Somar dois números:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "polar-boating",
   "metadata": {},
   "outputs": [],
   "source": [
    "def soma(a, b):\n",
    "    print(a+b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "strong-craft",
   "metadata": {},
   "source": [
    "A instrução `def` é usada para definir uma nova função. No exemplo acima, é criada a função `soma` que tem 2 argumentos `a` e `b` e o corpo da função, que nesse caso é dado por uma expressão apenas `print(a+b)`.\n",
    "\n",
    "Repare na indentação. Assim como no `if`, `while` e `for`, o corpo da função deve ser indentado.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "sexual-celebration",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "soma(1,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "great-republic",
   "metadata": {},
   "source": [
    "no exemplo acima, chamamos a função `soma` com os argumentos `1` e `2`. O argumento da função `a` assume o valor `1` e o argumento `b` assume o valor `2`.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "cathedral-nerve",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "soma(3,4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "matched-matter",
   "metadata": {},
   "source": [
    "Vamos fazer uma função parecida mas levemente diferente:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "pharmaceutical-central",
   "metadata": {},
   "outputs": [],
   "source": [
    "def soma2(a, b):\n",
    "    print(a + 2*b)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "potential-seventh",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "soma2(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "royal-greene",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "x = 1\n",
    "y = 2\n",
    "soma2(x,y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "single-inquiry",
   "metadata": {},
   "source": [
    "novamente, o argumento `a` assume o valor de `x` e o argumento `b` assume o valor de `y`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "anticipated-drawing",
   "metadata": {},
   "source": [
    "###  Exercício 1\n",
    "O que o programa a seguir vai imprimir?\n",
    "\n",
    "```python\n",
    "a = 1\n",
    "b = 2\n",
    "soma2(a,b)\n",
    "```\n",
    "\n",
    "e o programa\n",
    "```python\n",
    "a = 1\n",
    "b = 2\n",
    "soma2(b, a)\n",
    "```\n",
    "\n",
    "Tente explicar o que aconteceu."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "naughty-gravity",
   "metadata": {},
   "source": [
    "Os dois exemplos acima são bem simples mas ainda são diferentes do que observamos com funções matemáticas:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "temporal-bahrain",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "x = soma(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "hired-withdrawal",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Esperamos que o valor de `x` seja 3 (ou não...)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "realistic-taylor",
   "metadata": {},
   "source": [
    "A função pode retornar um valor. Então podemos reescrever a função `soma` da seguinte maneira:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "micro-cornwall",
   "metadata": {},
   "outputs": [],
   "source": [
    "def soma(a,b):\n",
    "    return a+b\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "wrapped-correlation",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = soma(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "signed-product",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "honey-watch",
   "metadata": {},
   "source": [
    "Agora temos algo que se comporta como as funções `len` ou `int` por exemplo.\n",
    "\n",
    "Na verdade esse é o melhor jeito de se escrever uma função: usando os argumentos e  o valor de retorno. A primeira versão é limitada. Não podemos usar diretamente o valor da soma. \n",
    "\n",
    "Se a pessoa que está usando a função quiser imprimir o valor da soma, \n",
    "ela pode chamar a função e imprimir o valor. Muito mais útil e flexível:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "unlike-hurricane",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "print(soma(1,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "australian-calgary",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "x = soma(1,2)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "green-knowing",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Função para determinar se número é par\n",
    "def é_par(x):\n",
    "    return x % 2 == 0 # Se o resto da divisão for zero, o número é par!\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "retained-hawaii",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(é_par(1))\n",
    "print(é_par(2))\n",
    "print(é_par(3))\n",
    "print(é_par(4))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "extraordinary-welding",
   "metadata": {},
   "source": [
    "\n",
    "**Uma função pode chamar outra!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "seventh-triple",
   "metadata": {},
   "outputs": [],
   "source": [
    "def par_ou_ímpar(x):\n",
    "    if é_par(x):\n",
    "        return \"par\"\n",
    "    else:\n",
    "        return \"ímpar\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "equivalent-formation",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ímpar\n",
      "par\n"
     ]
    }
   ],
   "source": [
    "print(par_ou_ímpar(5))\n",
    "print(par_ou_ímpar(32))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "oriented-vatican",
   "metadata": {},
   "source": [
    "### Exercício 2\n",
    "Escreva a função `máximo` que retorna o maior de dois números"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "united-consensus",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "contemporary-speaking",
   "metadata": {},
   "source": [
    "### Exercício 3\n",
    "Escreva a função `múltiplo` que retorna `True` se o primeiro argumento for um múltiplo do segundo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "prostate-chassis",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "involved-mauritius",
   "metadata": {},
   "source": [
    "### Exercício 4\n",
    "Escreva a função `área_quadrado` que recebe o lado de um quadrado e calcula a área."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "metric-beads",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "seeing-depth",
   "metadata": {},
   "source": [
    "### Exercício 5\n",
    "Escreve a função `área_triângulo` que recebe a base e a altura de um triângulo e retorna a sua área"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "finnish-michael",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "plain-guidance",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "brief-denmark",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Programa para pesquisar os elementos de uma lista:\n",
    "def pesquise(lista, valor):\n",
    "    for i,e in enumerate(lista):\n",
    "        if e == valor:\n",
    "            return i\n",
    "    return None\n",
    "\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "mediterranean-combat",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pesquise([1,2,3], 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "vertical-miami",
   "metadata": {},
   "outputs": [],
   "source": [
    "pesquise([1,2,3], 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "upset-stock",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pesquise([1,2,3], 4) == None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "solved-greensboro",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Programa para somar os elementos de uma lista:\n",
    "def soma(L):\n",
    "    total = 0\n",
    "    for v in L:\n",
    "        total += v\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "important-acrylic",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "soma([1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "lyric-methodology",
   "metadata": {},
   "outputs": [],
   "source": [
    "# A média dos elementos de uma lista\n",
    "def média(L):\n",
    "    total = 0\n",
    "    for v in L:\n",
    "        total += v\n",
    "    return total / len(L)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "challenging-console",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "média([1,2,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "close-script",
   "metadata": {},
   "source": [
    "Mas será que não dá para melhorar? A função é quase igual à função soma!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "original-character",
   "metadata": {},
   "outputs": [],
   "source": [
    "def média(L):\n",
    "    return soma(L) / len(L)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "changed-residence",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "média([1,2,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "rubber-dublin",
   "metadata": {},
   "source": [
    "**Como não escrever a função `soma`**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "appropriate-algebra",
   "metadata": {},
   "outputs": [],
   "source": [
    "def soma_ruim(L):\n",
    "    total = 0\n",
    "    i = 0\n",
    "    while i < 5:\n",
    "        total += L[i]\n",
    "        i += 1\n",
    "    return total\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "equal-bishop",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "soma_ruim([1,2,3,4,5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "measured-machine",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Porque isso dá errado???\n",
    "soma_ruim([1,2,3,4,5,6,7])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "spiritual-wireless",
   "metadata": {},
   "source": [
    "**Fatorial**\n",
    "\n",
    "O fatorial de um número inteiro positivo `n` é dado por \n",
    "\n",
    "$$\n",
    "n! = 1\\times 2 \\times 3 \\times \\ldots \\times n\n",
    "$$\n",
    "\n",
    "e o fatorial de zero é 1:\n",
    "$$\n",
    "0! = 1\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "industrial-toronto",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fatorial(n):\n",
    "    fat = 1\n",
    "    while n > 1:\n",
    "        fat *= n\n",
    "        n -= 1\n",
    "    return fat\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "reported-pulse",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "120"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fatorial(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "attached-journalism",
   "metadata": {},
   "source": [
    "Geralmente existem outras maneiras de escrever uma função:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "offshore-basket",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fatorial(n):\n",
    "    fat = 1\n",
    "    i = 1\n",
    "    while i <= n:\n",
    "        fat *= i\n",
    "        i += 1\n",
    "    return fat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "moderate-findings",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "120"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "fatorial(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "annoying-confusion",
   "metadata": {},
   "source": [
    "### Exercício 6\n",
    "Reescreve a função para pesquisar uma lista (`pesquise`) acima de modo a que use os métodos de pesquisa em lista que vimos na última aula."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "emerging-crisis",
   "metadata": {},
   "source": [
    "## Variáveis locais e globais\n",
    "\n",
    "As funções que escrevemos até aqui tinham argumentos e eventualmente uma variável *dentro* da função. Que valor essa variável dentro da função assume? E se tivermos uma variável com mesmo nome fora da função?\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "organic-facial",
   "metadata": {},
   "outputs": [],
   "source": [
    "EMPRESA = \"Unidos Venceremos LTDA\"\n",
    "def imprime_cabeçalho():\n",
    "    print(EMPRESA)\n",
    "    print(\"-\" * len(EMPRESA))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "pending-board",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Unidos Venceremos LTDA\n",
      "----------------------\n"
     ]
    }
   ],
   "source": [
    "imprime_cabeçalho()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "altered-somerset",
   "metadata": {},
   "source": [
    "Uma variável global é definida *fora* da função. Mas é aqui que as podem ficar confusas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "cosmetic-radical",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 5\n",
    "def teste(a):\n",
    "    print(a) # Que a estamos usando?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "id": "sacred-wrestling",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n"
     ]
    }
   ],
   "source": [
    "teste(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "interesting-habitat",
   "metadata": {},
   "source": [
    "Este caso a gente já viu! Dentro da função estamos usando o argumento da função."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "id": "active-address",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 5\n",
    "def teste2():\n",
    "    print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "conscious-ecology",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "teste2()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "swedish-packet",
   "metadata": {},
   "source": [
    "Este caso também está claro: estamos usando a variável global.\n",
    "\n",
    "E agora?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "balanced-provincial",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 5\n",
    "def teste3():\n",
    "    a = 7\n",
    "    print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "nasty-frost",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "teste3()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sensitive-individual",
   "metadata": {},
   "source": [
    "Beleza, nada inesperado. Mas agora que estamos fora da função, qual o valor de `a`???"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "possible-operation",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "proved-classics",
   "metadata": {},
   "source": [
    "Esquisito né? O que aconteceu?\n",
    "\n",
    "Ao executarmos a linha `a=7`, criamos uma nova variável **local**!\n",
    "\n",
    "Bom então no exemplo a seguir, vai imprimir 5 antes de mudar o valor (ou não???)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "acting-roads",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 5\n",
    "def teste4():\n",
    "    print(a)\n",
    "    a = 7\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "molecular-congress",
   "metadata": {},
   "outputs": [
    {
     "ename": "UnboundLocalError",
     "evalue": "local variable 'a' referenced before assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mUnboundLocalError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/2345248876.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mteste4\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/tmp/ipykernel_9884/3050936089.py\u001b[0m in \u001b[0;36mteste4\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mteste4\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m     \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m7\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'a' referenced before assignment"
     ]
    }
   ],
   "source": [
    "teste4()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "continuous-arrow",
   "metadata": {},
   "source": [
    "QUE É QUE ACONTECEU???? O PYTHON FICOU LOUCO\n",
    "\n",
    "(ou não...)\n",
    "\n",
    "O que ocorre é que existe uma atribuição de `a` dentro da função. Isso automaticamente faze com que **`a` se torne uma variável local**. Então a função nem sabe da existência da variável global `a` e portanto dá erro!\n",
    "\n",
    "Mas e se eu quiser modificar o valor da variável global `a`? Use a instrução `global`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "under-strategy",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Antes de chamar a função: 5\n",
      "Dentro da função: 7\n",
      "Depois de chamar a função: 7\n"
     ]
    }
   ],
   "source": [
    "a = 5\n",
    "def teste5():\n",
    "    global a    # Olha o global aqui!\n",
    "    a = 7\n",
    "    print(f\"Dentro da função: {a}\")\n",
    "print(f\"Antes de chamar a função: {a}\")\n",
    "teste5()\n",
    "print(f\"Depois de chamar a função: {a}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "prepared-belgium",
   "metadata": {},
   "source": [
    "### Recomendações\n",
    "\n",
    "**EVITE USAR VARIÁVEIS GLOBAIS**. Quando você usa variáveis globais, o que uma função faz depende do estado do programa. Isso pode introduzir erros difíceis de serem diagnosticados. Se possível, passe o que seria uma variável global como um novo argumento da função. \n",
    "\n",
    "Se você estiver usando variáveis globais, provavelmente você não pensou bem na estrutura do teu programa. \n",
    "\n",
    "É lógico que isso não é dogma e variáveis globais podem ser úteis, por exemplo alguma configuração do programa. \n",
    "\n",
    "Mas sempre pense duas (3, 4, 5) vezes antes de usar variáveis globais."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "tested-proposition",
   "metadata": {},
   "source": [
    "## Funções recursivas\n",
    "Já vimos que uma função pode chamar outra. Mas uma função pode chamar a si mesma! Esta é uma função recursiva.\n",
    "\n",
    "Lembra da função fatorial? Bom, ela pode ser definida da seguinte maneira:\n",
    "\n",
    "$$\n",
    "0! = 1\n",
    "$$\n",
    "$$\n",
    "1! = 1\n",
    "$$\n",
    "$$\n",
    "n! = n \\times (n-1)! \n",
    "$$\n",
    "\n",
    "Com essa definição, "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "jewish-level",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fatorial(n):\n",
    "    if n <= 1:\n",
    "        return 1\n",
    "    else:\n",
    "        return n * fatorial(n-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "hundred-torture",
   "metadata": {},
   "source": [
    "Repare que é importante que exista uma condição de parada! Caso contrário a recursão não parará e o programa será executado até ocorrer o erro `RecursionError`. \n",
    "\n",
    "Este erro ocorre pois a memória pode estourar (na verdade a pilha). Isso é equivalente ao loop infinito que já vimos para o `while` mas nesse caso, pode não ocorrer um erro."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "certified-composite",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fatorial_errado(n):\n",
    "    return n * fatorial_errado(n-1)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "subject-cambodia",
   "metadata": {},
   "outputs": [
    {
     "ename": "RecursionError",
     "evalue": "maximum recursion depth exceeded",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRecursionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/3944653170.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfatorial_errado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/tmp/ipykernel_9884/3407553999.py\u001b[0m in \u001b[0;36mfatorial_errado\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfatorial_errado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mfatorial_errado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "... last 1 frames repeated, from the frame below ...\n",
      "\u001b[0;32m/tmp/ipykernel_9884/3407553999.py\u001b[0m in \u001b[0;36mfatorial_errado\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfatorial_errado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mfatorial_errado\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded"
     ]
    }
   ],
   "source": [
    "fatorial_errado(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "collective-novel",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vamos rastrear o fatorial?\n",
    "def fatorial_rastreado(n):\n",
    "    print(f\"Calculando o fatorial de {n}\")\n",
    "    if n==0 or n==1:\n",
    "        print(f\"Fatorial de {n} = 1\")\n",
    "        return 1\n",
    "    else:\n",
    "        fat = n * fatorial_rastreado(n-1)\n",
    "        print(f\" fatorial de {n} = {fat}\")\n",
    "    return fat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "prostate-february",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculando o fatorial de 4\n",
      "Calculando o fatorial de 3\n",
      "Calculando o fatorial de 2\n",
      "Calculando o fatorial de 1\n",
      "Fatorial de 1 = 1\n",
      " fatorial de 2 = 2\n",
      " fatorial de 3 = 6\n",
      " fatorial de 4 = 24\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "24"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fatorial_rastreado(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "banner-channels",
   "metadata": {},
   "source": [
    "**Sequência de Fibonacci**\n",
    "\n",
    "Se $n \\le 1$, \n",
    "\n",
    "`fibonacci(n) = 1`\n",
    "\n",
    "caso contrário,\n",
    "\n",
    "`fibonacci(n) = fibonacci(n-1) + fibonacci(n-2)`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "sapphire-field",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fibonacci(n):\n",
    "    if n <= 1:\n",
    "        return n\n",
    "    else:\n",
    "        return fibonacci(n-1) + fibonacci(n-2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "compressed-kennedy",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6765"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fibonacci(20)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efficient-arthur",
   "metadata": {},
   "source": [
    "### Exercício 7\n",
    "Defina uma função recursive que calcule o maior divisor comum (MDC) entre dois números a e b em que a > b.\n",
    "\n",
    "`mdc(a,b) = a` se `b==0` e se `a > b`, `mdc(a,b) = mdc(b, a % b)`\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "weird-neutral",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "billion-germany",
   "metadata": {},
   "source": [
    "### Exercício 8\n",
    "Usando a função `mdc` do exercício anterior, defina uma função para calcular o mínimo múltiplo comum (MMC) entre dois números:\n",
    "\n",
    "$$\n",
    "mmc(a,b) = \\frac{|a\\times b|}{mdc(a,b)}\n",
    "$$\n",
    "\n",
    "Lembre que $|a \\times b|$ é escrito como `abs(a * b)` em Python."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "intelligent-washington",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "thousand-charlotte",
   "metadata": {},
   "source": [
    "### Exercício 9\n",
    "Reescreva o programa para calcular a sequência de Fibonacci sem utilizar recursão.\n",
    "\n",
    "Compare o desempenho com a função recursiva. Se você estiver usando o notebook do jupyter ou o ipython você pode usar a instrução `%time` como mostrado a seguir"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "potential-moral",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 23 µs, sys: 1e+03 ns, total: 24 µs\n",
      "Wall time: 25.5 µs\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time fibonacci(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "moral-northern",
   "metadata": {},
   "source": [
    "Pense no desempenho destas duas implementações. Consegue explicar?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "announced-concrete",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "responsible-stereo",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "natural-personal",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "primary-syndrome",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "mounted-default",
   "metadata": {},
   "source": [
    "## Parâmetros opcionais\n",
    "\n",
    "Algumas vezes, os parâmetros da função podem ter valores típicos que mudam pouco. Então podemos usar um parâmetro opcional. Este parâmetro opcional, se não for fornecido, terá um valor padrão, definido junto com a função."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "id": "adopted-clothing",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Função para desenhar uma barra\n",
    "def barra():\n",
    "    return '*'*40\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "id": "sufficient-fellowship",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'****************************************'"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "barra()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "smooth-seafood",
   "metadata": {},
   "source": [
    " Mas eu quero especificar o número de caracteres:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "general-philadelphia",
   "metadata": {},
   "outputs": [],
   "source": [
    "def barra(n):\n",
    "    return '*' * n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "conventional-forestry",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "************************************************************\n",
      "********************\n"
     ]
    }
   ],
   "source": [
    "print(barra(40))  # Equivalente ao primeiro \n",
    "print(barra(60))\n",
    "print(barra(20))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mature-flash",
   "metadata": {},
   "source": [
    "Mas e seu quiser usar um caracter diferente? Use um outro argumento!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "id": "gross-appliance",
   "metadata": {},
   "outputs": [],
   "source": [
    "def barra(n, caracter):\n",
    "    return caracter * n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "strange-allen",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "========================================\n"
     ]
    }
   ],
   "source": [
    "print(barra(40, '*'))\n",
    "print(barra(40, '='))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "seventh-blocking",
   "metadata": {},
   "source": [
    "Mas agora eu preciso ficar digitando o caracter também ?!?\n",
    "\n",
    "Use um argumento opcional!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "three-designer",
   "metadata": {},
   "outputs": [],
   "source": [
    "def barra(n, caracter='*'):\n",
    "    return caracter * n    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "tribal-prison",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "========================================\n"
     ]
    }
   ],
   "source": [
    "print(barra(40))\n",
    "print(barra(40, '='))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adequate-tamil",
   "metadata": {},
   "source": [
    "Mas geralmente vou usar 40 caracteres!\n",
    "\n",
    "Então use outro argumento opcional!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "thermal-lobby",
   "metadata": {},
   "outputs": [],
   "source": [
    "def barra(n=40, caracter='*'):\n",
    "    return caracter * n    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "transsexual-uruguay",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "********************\n",
      "----------------------------------------\n",
      "--------------------\n"
     ]
    }
   ],
   "source": [
    "print(barra())\n",
    "print(barra(20))\n",
    "print(barra(40, '-'))\n",
    "print(barra(20, '-'))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "social-backing",
   "metadata": {},
   "source": [
    "## Nomeando parâmetros\n",
    "\n",
    "Python é ainda mais flexível ainda! Você pode usar os parâmetros pelo nome!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "stylish-exclusive",
   "metadata": {},
   "outputs": [],
   "source": [
    "def retângulo(largura, altura, caracter):\n",
    "    linha = caracter * largura\n",
    "    for i in range(altura):\n",
    "        print(linha)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "id": "comparable-scott",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "********************\n",
      "********************\n",
      "********************\n",
      "********************\n"
     ]
    }
   ],
   "source": [
    "# Como fizemos até aqui.\n",
    "retângulo(20, 4, '*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "detected-execution",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+++++++++++++++\n",
      "+++++++++++++++\n",
      "+++++++++++++++\n"
     ]
    }
   ],
   "source": [
    "# Podemos fazer isso:\n",
    "retângulo(caracter='+', altura=3, largura=15)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "banner-assumption",
   "metadata": {},
   "source": [
    "E podemos combinar isso com is argumentos opcionais:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "satisfied-comedy",
   "metadata": {},
   "outputs": [],
   "source": [
    "def retângulo(largura=20, altura=4, caracter='*'):\n",
    "    linha = caracter * largura\n",
    "    for i in range(altura):\n",
    "        print(linha)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "warming-xerox",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "********************\n",
      "********************\n",
      "********************\n",
      "********************\n"
     ]
    }
   ],
   "source": [
    "retângulo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "supreme-design",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "++++++++++++++++++++\n",
      "++++++++++++++++++++\n",
      "++++++++++++++++++++\n",
      "++++++++++++++++++++\n"
     ]
    }
   ],
   "source": [
    "retângulo(caracter='+')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "quick-bookmark",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n"
     ]
    }
   ],
   "source": [
    "retângulo(largura=40)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "id": "specific-bolivia",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n",
      "****************************************\n"
     ]
    }
   ],
   "source": [
    "retângulo(largura=40, altura=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "id": "royal-daisy",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n",
      "----------------------------------------\n"
     ]
    }
   ],
   "source": [
    "retângulo(largura=40, caracter='-', altura=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "white-narrow",
   "metadata": {},
   "source": [
    "Isso é muito bom quando a função tem vários argumentos."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "occasional-width",
   "metadata": {},
   "source": [
    "## Funções como parâmetro\n",
    "\n",
    "Até agora, os parâmetros das funções foram variáveis numéricas, listas, etc. Pode ser também uma função!\n",
    "\n",
    "É isso mesmo. Uma função pode ser passada como um parâmetro em outra chamada de função!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "id": "integral-kernel",
   "metadata": {},
   "outputs": [],
   "source": [
    "def soma(a,b):\n",
    "    return a+b\n",
    "def subtração(a,b):\n",
    "    return a-b\n",
    "def multiplicação(a,b):\n",
    "    return a*b\n",
    "\n",
    "def imprime(a, b, foper):\n",
    "    print(foper(a,b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "id": "norman-bronze",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "3\n",
      "10\n"
     ]
    }
   ],
   "source": [
    "imprime(5,2,soma)\n",
    "imprime(5,2,subtração)\n",
    "imprime(5,2,multiplicação)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "facial-turkish",
   "metadata": {},
   "source": [
    "Parece esquisito. Será que tem uso? \n",
    "\n",
    "Ahhhh, muito. Permite você flexibilizar o teu programa. Dar funcionalidade nova. Fazendo isso bem, o teu usuário vai poder usar as tuas funções de maneiras que você nunca imaginou."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "id": "classical-straight",
   "metadata": {},
   "outputs": [],
   "source": [
    "def imprime_lista(L, fimpressão, fcondição):\n",
    "    for e in L:\n",
    "        if fcondição(e):\n",
    "            fimpressão(e)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "id": "fabulous-element",
   "metadata": {},
   "outputs": [],
   "source": [
    "def imprime_elemento(e):\n",
    "    print(f\"Valor: {e}\")\n",
    "def épar(x):\n",
    "    return x % 2 == 0\n",
    "def éímpar(x):\n",
    "    return not épar(x)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "id": "pregnant-output",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Valor: 2\n",
      "Valor: 0\n"
     ]
    }
   ],
   "source": [
    "L = [1,7,9,2,11,0]\n",
    "imprime_lista(L, imprime_elemento, épar)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "id": "satellite-boston",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Valor: 1\n",
      "Valor: 7\n",
      "Valor: 9\n",
      "Valor: 11\n"
     ]
    }
   ],
   "source": [
    "imprime_lista(L, imprime_elemento, éímpar)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ready-penguin",
   "metadata": {},
   "source": [
    "### Exercício 10\n",
    "Na aula 03 implementamos o algoritmo de reordenação de listas bubble sort. Crie uma função `bubble_sort` que reordena os elementos de uma lista de números em ordem crescente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "powerful-modeling",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "under-saturday",
   "metadata": {},
   "source": [
    "### Exercício 11\n",
    "Mude o programa do exercício 10 de modo que tenha um segundo parâmetro `comparador` que é uma função que compara dois elementos\n",
    "```python\n",
    "def maior(a, b):\n",
    "    return a > b\n",
    "\n",
    "def bubble_sort(L, comparador=maior)\n",
    "    # Corpo da função\n",
    "```\n",
    "Esse segundo parâmetro é o que compara os elementos da lista. Se esse parâmetros for a função `maior`, a lista será reordenada em ordem crescente.\n",
    "\n",
    "Qual seria a função passada para o parâmetro `comparador` para que a lista fosse reordenada em ordem decrescente?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "affecting-stations",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "consistent-gazette",
   "metadata": {},
   "source": [
    "### Exercício 12\n",
    "Escreva uma função `mapa` que recebe como primeiro parâmetro uma função e segundo parâmetro uma lista e cria uma nova lista aplicando esta função em cada elemento da lista. \n",
    "    \n",
    "\n",
    "Exemplo:\n",
    "```python-repl\n",
    "In [10]: def dobro(n):\n",
    "    ...:     return 2*n\n",
    "    ...: \n",
    "\n",
    "In [11]: mapa(dobro, [1,2,3])\n",
    "Out[11]: [2, 4, 6]\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "rubber-calendar",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "id": "electronic-shannon",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]"
      ]
     },
     "execution_count": 171,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "indoor-adoption",
   "metadata": {},
   "source": [
    "## List comprehension\n",
    "\n",
    "No exercício 12, criamos uma função que aplica uma função a cada elemento de uma lista. Isso é tão útil que os criadores do Python implementaram uma sintaxe útil e simples para fazer isso: *List Comprehension*.\n",
    "\n",
    "Com isso, muitas vezes o código fica mais curto e legível. Você nem precisa implementar laços e coisas parecidas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "id": "important-layout",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
      ]
     },
     "execution_count": 173,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = [x for x in range(10)]\n",
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "id": "weird-coordinate",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]"
      ]
     },
     "execution_count": 175,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = [2*x for x in L]\n",
    "Z"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "assumed-congo",
   "metadata": {},
   "source": [
    "Dá para criar coisas mais complexas:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "id": "reasonable-diving",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 0, 0),\n",
       " (1, 2, 1),\n",
       " (2, 4, 4),\n",
       " (3, 6, 9),\n",
       " (4, 8, 16),\n",
       " (5, 10, 25),\n",
       " (6, 12, 36),\n",
       " (7, 14, 49),\n",
       " (8, 16, 64),\n",
       " (9, 18, 81)]"
      ]
     },
     "execution_count": 176,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[(x, 2*x, x*x) for x in L]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "central-leadership",
   "metadata": {},
   "source": [
    "É funciona com outros tipos de dados. Na verdade com qualquer tipo de dado indexável:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "id": "bizarre-necklace",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['A', 'B', 'C', 'D', 'E', 'F', 'G']"
      ]
     },
     "execution_count": 177,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = [s.upper() for s in \"abcdefg\"]\n",
    "Z"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "accompanied-printing",
   "metadata": {},
   "source": [
    "**o melhor de tudo é que dá para filtrar as coisas**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "id": "fifty-insert",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8]"
      ]
     },
     "execution_count": 181,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p = [x for x in range(10) if x % 2 == 0]  # Só os pares\n",
    "p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "flush-premium",
   "metadata": {},
   "source": [
    "## Tipo de uma variável. A função `type`\n",
    "\n",
    "Em Python **todas** as variáveis e objetos têm um tipo. Você pode inspecionar isso usando a função `type`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 183,
   "id": "irish-ladder",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 183,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "id": "provincial-copying",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "float"
      ]
     },
     "execution_count": 185,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(1.23)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 186,
   "id": "confident-large",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str"
      ]
     },
     "execution_count": 186,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(\"IPT\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 187,
   "id": "outer-radical",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 187,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type([1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "id": "instructional-pregnancy",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 188,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type({'a':1, 'b':2})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "id": "interracial-jumping",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "set"
      ]
     },
     "execution_count": 190,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type({1,2,3,4})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "id": "moving-leadership",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "builtin_function_or_method"
      ]
     },
     "execution_count": 197,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(len)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "similar-basketball",
   "metadata": {},
   "source": [
    "Quando você está escrevendo uma função, é útil verificar se um parâmetro tem um tipo específico. Para isso existe a função `isinstance` que verifica se um objeto é de um tipo específico ou de uma lista de tipos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "id": "composite-standing",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 198,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance(1, int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 204,
   "id": "provincial-guidance",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 204,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance(1, float)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 206,
   "id": "seventh-street",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 206,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance(1, (float,int))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 207,
   "id": "searching-aging",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 207,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance([1,2,3], list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "id": "directed-frontier",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 209,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance((1,2,3), tuple)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 211,
   "id": "economic-running",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 211,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance((1,2,3), list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 213,
   "id": "functional-model",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 213,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance((1,2,3), (list, tuple))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 214,
   "id": "cubic-convenience",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 214,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isinstance([1,2,3], (list, tuple))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 215,
   "id": "british-applicant",
   "metadata": {},
   "outputs": [],
   "source": [
    "import types # Módulo da biblioteca padrão para tipos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 227,
   "id": "needed-bride",
   "metadata": {},
   "outputs": [],
   "source": [
    "def diz_o_tipo(a):\n",
    "    if isinstance(a, str):\n",
    "        return 'String'\n",
    "    elif isinstance(a, list):\n",
    "        return 'Lista'\n",
    "    elif isinstance(a, dict):\n",
    "        return 'Dicionário'\n",
    "    elif isinstance(a, int):\n",
    "        return 'Número inteiro'\n",
    "    elif isinstance(a, float):\n",
    "        return 'Número decimal'\n",
    "    elif isinstance(a, types.FunctionType):\n",
    "        return 'Função'\n",
    "    elif isinstance(a, types.BuiltinFunctionType):\n",
    "        return 'Função interna'\n",
    "    else:\n",
    "        return str(type(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 217,
   "id": "pharmaceutical-strap",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Número inteiro'"
      ]
     },
     "execution_count": 217,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 218,
   "id": "funky-gossip",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Lista'"
      ]
     },
     "execution_count": 218,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo([1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "id": "employed-litigation",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Número decimal'"
      ]
     },
     "execution_count": 219,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo(1.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 223,
   "id": "photographic-processing",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Função interna'"
      ]
     },
     "execution_count": 223,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo(len)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 225,
   "id": "double-namibia",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Função'"
      ]
     },
     "execution_count": 225,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo(diz_o_tipo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 228,
   "id": "decimal-taste",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"<class 'tuple'>\""
      ]
     },
     "execution_count": 228,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "diz_o_tipo((1,2,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "brave-plumbing",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "danish-saskatchewan",
   "metadata": {},
   "source": [
    "## Exceções\n",
    "\n",
    "Várias vezes ocorrem erros no programa. Neste curso fizemos alguns erros de propósto para mostrar funcionalidade e algumas vezes sem querer mesmo ao digitar algo errado. \n",
    "\n",
    "Quando estes erros ocorreram, o programa simplesmente foi interrompido. Isso não é nem um pouco legal. Imagina você está usando um programa e de repente porque você digitou algo o programa acusa um erro e sai. Este não é o melhor dos mundos...\n",
    "\n",
    "Em python um erro é conhecido como uma exceção (*exception* em inglês)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 180,
   "id": "invisible-stone",
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/2673955037.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mL\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mL\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m: list index out of range"
     ]
    }
   ],
   "source": [
    "L = [1,2,3]\n",
    "\n",
    "L[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 230,
   "id": "ecological-preparation",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "invalid literal for int() with base 10: 'IPT'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/2167290565.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"IPT\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'IPT'"
     ]
    }
   ],
   "source": [
    "int(\"IPT\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "supported-emission",
   "metadata": {},
   "source": [
    "Repare que existem diferentes tipos de exceções!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 234,
   "id": "single-sapphire",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Digite o número que quer imprimir: jhkasdasd\n",
      "O programa só aceita número\n",
      "Digite o número que quer imprimir: 10\n",
      "Valor inválido, digite entre -3 e 3!\n",
      "Digite o número que quer imprimir: 1\n",
      "Carlos\n"
     ]
    }
   ],
   "source": [
    "# Capturando uma exceção:\n",
    "nomes = [\"Ana\", \"Carlos\", \"Maria\"]\n",
    "for tentativa in range(3):\n",
    "    try:\n",
    "        i = int(input(\"Digite o número que quer imprimir: \"))\n",
    "        print(nomes[i])\n",
    "        break\n",
    "    except ValueError:\n",
    "        print(\"O programa só aceita número\")\n",
    "    except IndexError:\n",
    "        print(f\"Valor inválido, digite entre -3 e 3!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 240,
   "id": "cellular-omaha",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Digite o número que quer imprimir: 6\n",
      "Algum erro na entrada: list index out of range\n",
      "Digite o número que quer imprimir: 6\n",
      "Algum erro na entrada: list index out of range\n",
      "Digite o número que quer imprimir: 6\n",
      "Algum erro na entrada: list index out of range\n"
     ]
    }
   ],
   "source": [
    "# Outra possibilidade:\n",
    "# Capturando uma exceção:\n",
    "nomes = [\"Ana\", \"Carlos\", \"Maria\"]\n",
    "for tentativa in range(3):\n",
    "    try:\n",
    "        i = int(input(\"Digite o número que quer imprimir: \"))\n",
    "        print(nomes[i])\n",
    "        break\n",
    "    except Exception as e:\n",
    "        print(f\"Algum erro na entrada: {e}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "intended-ceramic",
   "metadata": {},
   "source": [
    "Caso finalmente dê certo, existe a declaração `finally`. Essa parte sempre é executada!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 241,
   "id": "surprising-ethnic",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Digite o número que quer imprimir: 5\n",
      "Algum erro na entrada: list index out of range\n",
      "Tentativa 1\n",
      "Digite o número que quer imprimir: 5\n",
      "Algum erro na entrada: list index out of range\n",
      "Tentativa 2\n",
      "Digite o número que quer imprimir: 5\n",
      "Algum erro na entrada: list index out of range\n",
      "Tentativa 3\n",
      "FIM\n"
     ]
    }
   ],
   "source": [
    "nomes = [\"Ana\", \"Carlos\", \"Maria\"]\n",
    "for tentativa in range(3):\n",
    "    try:\n",
    "        i = int(input(\"Digite o número que quer imprimir: \"))\n",
    "        print(nomes[i])\n",
    "        break\n",
    "    except Exception as e:\n",
    "        print(f\"Algum erro na entrada: {e}\")\n",
    "    finally: \n",
    "        print(f\"Tentativa {tentativa+1}\")\n",
    "print(\"FIM\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 242,
   "id": "understanding-messenger",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "math domain error",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/2272264683.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m: math domain error"
     ]
    }
   ],
   "source": [
    "math.sqrt(-1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fewer-probability",
   "metadata": {},
   "source": [
    "## Módulos\n",
    "\n",
    "Ao se fazer um programa, escrevem-se funções para se realizar diferentes coisas. Estas funções podem ser úteis em outros programas. Então é interessante reaproveitar o teu trabalho. Com o decorrer do tempo, se você for organizado, você pode ter uma biblioteca de funções que são extremamente úteis e economizam um tempo danado.\n",
    "\n",
    "O mecanismo básico para isso é o *módulo*. O módulo é um arquivo com terminação `.py` com funções (e outras coisas). Em geral está na mesma pasta que o programa que você está desenvolvendo. Como exemplo, vejamos o módulo `utilidade.py`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 274,
   "id": "victorian-membrane",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/home/pjabardo/Documents/assipt/pythonassipt'"
      ]
     },
     "execution_count": 274,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 275,
   "id": "meaningful-guinea",
   "metadata": {},
   "outputs": [],
   "source": [
    "import utilidades"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 278,
   "id": "vocal-industry",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sim ou Não? (s/n): n\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 278,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "utilidades.sim_ou_não(\"Sim ou Não?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 280,
   "id": "fluid-rings",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Entre com um número: asd\n",
      "Valor ilegal - could not convert string to float: 'asd'! Tente novamente!\n",
      "Entre com um número: asd\n",
      "Valor ilegal - could not convert string to float: 'asd'! Tente novamente!\n",
      "Entre com um número: asd\n",
      "Valor ilegal - could not convert string to float: 'asd'! Tente novamente!\n",
      "Entre com um número: asd\n",
      "Valor ilegal - could not convert string to float: 'asd'! Tente novamente!\n",
      "Entre com um número: asd\n",
      "Valor ilegal - could not convert string to float: 'asd'! Tente novamente!\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "Nenhum valor fornecido",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_9884/596805572.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mutilidades\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mentrada_float\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Entre com um número: \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/Documents/assipt/pythonassipt/utilidades.py\u001b[0m in \u001b[0;36mentrada_float\u001b[0;34m(msg, xmin, xmax, ntentativas, x)\u001b[0m\n\u001b[1;32m     22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     23\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mentrada_float\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxmin\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxmax\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mntentativas\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 24\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mentrada\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxmin\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mxmax\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mntentativas\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     25\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     26\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconverter_sn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/Documents/assipt/pythonassipt/utilidades.py\u001b[0m in \u001b[0;36mentrada\u001b[0;34m(msg, converter, xmin, xmax, ntentativas, x)\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     15\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m         \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Nenhum valor fornecido\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     17\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     18\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: Nenhum valor fornecido"
     ]
    }
   ],
   "source": [
    "utilidades.entrada_float(\"Entre com um número: \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "british-drinking",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
