{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "earlier-commitment",
   "metadata": {},
   "source": [
    "# Aula 07: Classes e objetos\n",
    "\n",
    "Nessa aula vamos introduzir o conceito de classes e objetos e os fundamentos de programação orientada por objetos.\n",
    "\n",
    "Esse é um assunto complexo e extenso e a idéia aqui é passar os fundamentos em Python. A idéia é entender a diferença entre método e função e como usar classes e objetos em Python mais do que criá-las você mesmo. \n",
    "\n",
    "<!-- TEASER_END -->\n",
    "\n",
    "Esta aula está baseadano capítulo 10 do livro [Introdução à Progamação com PYTHON](https://novatec.com.br/livros/introducao-python-3ed/) de Nilo Ney Coutinho Menezes, 3a edição, editora Novatec.\n",
    "\n",
    "Começamos o curso usando o Python como uma calculadora. Depois introduzimos variáveis, estruturas de dados e funções. Á medida que o curso avançou reutilizamos todas os conceitos anteriores. \n",
    "\n",
    "De certa maneira, qualquer programa, por maior e mais complexo ele seja, é formado de elementos básicos como os que vimos até o momento. A dificuldade na programação é enxergar a floresta sem se perder com as árvores. Qualquer linha é facilmente compreensível se a linguagem de programação for minimamente conhecida.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "earned-guidance",
   "metadata": {},
   "source": [
    "\n",
    "## Programação orientada por objetos (POO)\n",
    "Entender o que um pedaço de código faz é bem mais complexo, assim como escrever o código. Essa dificuldade permeia toda a história da ciência da computação. Uma das \"soluções\" para este problema foi a orientação por objetos. \n",
    "\n",
    "\n",
    "Neste paradigma, *objetos* representam o problema e um programa é feito através da comunicação entre os objetos através de métodos. Em algumas linguagens como Smalltalk, esse conceito é levado literalmente.\n",
    "\n",
    "Não existe definição simples de OOP. Mas alguns conceitos são recorrentes:\n",
    "\n",
    " * Objetos\n",
    " * Classes\n",
    " * Encapsulamento\n",
    " * Herança\n",
    "\n",
    "Veremos brevemente esses conceitos aplicados a Python\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "amended-cedar",
   "metadata": {},
   "source": [
    "## Objetos como representação do mundo real\n",
    "\n",
    "Um objeto é uma representação de algo no mundo real, uma representação idealizada e simplificada do mundo real.\n",
    "\n",
    "Imagine uma televisão. Ela tem algumas características:\n",
    "\n",
    " * Pode ser ligada ou desligada\n",
    " * Ela está sintonizada em um canal\n",
    " * Pode aumentar ou diminuir o som\n",
    " * Muitas outras coisas (numa tv moderna)\n",
    " \n",
    "Então vamos usar uma classe `Televisão` para caracterizar uma televisão:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "digital-strap",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Televisão:  # Definição de uma classe\n",
    "    def __init__(self):  # Método especial - construtor\n",
    "        self.ligada = False # atributo \n",
    "        self.canal = 2 # outro atributo"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "federal-aurora",
   "metadata": {},
   "source": [
    "Agora podemos criar um objeto `Televisão` que pode representar uma TV:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "useful-nashville",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv = Televisão()  # Criar um objeto `Televisão`\n",
    "tv.ligada"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "sought-conditioning",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv.canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "smaller-heating",
   "metadata": {},
   "outputs": [],
   "source": [
    "tv_sala = Televisão() # Outro objeto da classe televisão\n",
    "tv_sala.ligada = True  # Estou ligando a televisão\n",
    "tv_sala.canal = 4  # Mudei o canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "informed-buffalo",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv.ligada"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "simplified-logic",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv_sala.ligada"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "wrapped-specialist",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv.canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "nuclear-springer",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv_sala.canal"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "removed-jungle",
   "metadata": {},
   "source": [
    "O método `__init__` é um método especial usado na construção de objetos de uma classe. Ele é conhecido como construtor."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "modern-blues",
   "metadata": {},
   "source": [
    "### Exercício 1\n",
    "Adicione atributos tamanho e marca à classe `Televisão`. Crie dois objetos `Televisão`  e atribua  tamanhos e marcas diferentes. Aí imprima  os atribuitos para ver a diferença"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "documented-raleigh",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "recent-black",
   "metadata": {},
   "source": [
    "Vamos dar alguma funcionalidade à class `Televisão`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "honey-colors",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Televisão:\n",
    "    def __init__(self):\n",
    "        self.ligada = False\n",
    "        self.canal = 2\n",
    "        \n",
    "    def muda_canal_para_baixo(self):\n",
    "        self.canal -= 1\n",
    "    def muda_canal_para_cima(self):\n",
    "        self.canal += 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "norman-browse",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv = Televisão()\n",
    "tv.canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "driving-petite",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv.muda_canal_para_cima()\n",
    "tv.muda_canal_para_cima()\n",
    "tv.canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "consistent-schedule",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tv.muda_canal_para_baixo()\n",
    "tv.canal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "minute-madagascar",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "greatest-burlington",
   "metadata": {},
   "source": [
    "## Passagem de parâmetros\n",
    "\n",
    "Será que pode ter canal negativo? Ou o canal 8723245?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "tutorial-evening",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Televisão:\n",
    "    def __init__(self, min, max):\n",
    "        self.ligada = False\n",
    "        self.canal = 2\n",
    "        self.cmin = min\n",
    "        self.cmax = max\n",
    "        \n",
    "    def muda_canal_para_baixo(self):\n",
    "        if self.canal -1 >= self.cmin:\n",
    "            self.canal -= 1\n",
    "    \n",
    "    def muda_canal_para_cima(self):\n",
    "        if self.canal +1 <= self.cmax:\n",
    "            self.canal += 1\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "minute-corps",
   "metadata": {},
   "outputs": [],
   "source": [
    "tv = Televisão(2,13)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "pediatric-translator",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13\n"
     ]
    }
   ],
   "source": [
    "for i in range(100):\n",
    "    tv.muda_canal_para_cima()\n",
    "print(tv.canal)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "favorite-contamination",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "for i in range(100):\n",
    "    tv.muda_canal_para_baixo()\n",
    "print(tv.canal)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "optical-devil",
   "metadata": {},
   "source": [
    "### Exercício 2\n",
    "\n",
    "Atualmente a classe `Televisão` inicializa o canal com 2. Modifique a classe de forma a receber o canal inicial em seu construtor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "australian-worthy",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "demonstrated-blond",
   "metadata": {},
   "source": [
    "### Exercício 3\n",
    "Modifique a classe `Televisão` de modo que se pedirmos para mudar o canal para baixo, além do mínimo, ele vái para o máximo e vice e versa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "missing-directive",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "twenty-highland",
   "metadata": {},
   "source": [
    "### Exercício 4\n",
    "Utilizando o que aprendemos com funções modifique o construtor de classe `Telefisão` de forma que `min` e `max` sejam parâmetros opcionais em que `min` vale 2 e `max` vale 13 caso outros valores não sejam passados"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "greenhouse-retirement",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "reflected-continuity",
   "metadata": {},
   "source": [
    "### Exercício 5\n",
    "Utilizando a classe modificada no exercício anterior (4), crie duas instâncias (objetos) especificando `min` e `max` por nome."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "minus-mining",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "described-inspection",
   "metadata": {},
   "source": [
    "## Exemplo de um Banco\n",
    "\n",
    "Vamos tentar modelar contas correntes de um banco"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "colonial-circuit",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Cliente:\n",
    "    def __init__(self, nome, telefone):\n",
    "        self.nome = nome\n",
    "        self.telefone = telefone\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "opposite-halifax",
   "metadata": {},
   "outputs": [],
   "source": [
    "joão = Cliente(\"João da Silva\", \"555-0178\")\n",
    "bozo = Cliente(\"Bozo Palhaço\", \"236-0873\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "broadband-niagara",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'João da Silva'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "joão.nome"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "excessive-malawi",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.Cliente"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(joão)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "manufactured-arrangement",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'555-0178'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "joão.telefone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "public-auditor",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Bozo Palhaço'"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bozo.nome"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "funny-structure",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'236-0873'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bozo.telefone"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "certain-religion",
   "metadata": {},
   "source": [
    "Em geral vamos armazenar isso num módulo. Para isso criamos o arquivo `clientes.py` e importamos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "funky-chase",
   "metadata": {},
   "outputs": [],
   "source": [
    "from clientes import Cliente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "miniature-palmer",
   "metadata": {},
   "outputs": [],
   "source": [
    "joão = Cliente(\"João da Silva\", \"555-0178\")\n",
    "bozo = Cliente(\"Bozo Palhaço\", \"236-0873\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "deadly-lewis",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "clientes.Cliente"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(joão)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "informal-correction",
   "metadata": {},
   "source": [
    "Agora precisamos de um outro módulo para armazenar a class `Conta` que representa uma conta corrente."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "sixth-excellence",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Código para recarregar automaticamente os módulos que \n",
    "\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "floating-pizza",
   "metadata": {},
   "outputs": [],
   "source": [
    "from contas import Conta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "matched-visiting",
   "metadata": {},
   "outputs": [],
   "source": [
    "conta = Conta(joão, \"234.567-01\", 1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "proper-domain",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:    1000.00\n"
     ]
    }
   ],
   "source": [
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "beneficial-chicago",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:     900.00\n"
     ]
    }
   ],
   "source": [
    "conta.saque(100)\n",
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "built-macro",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:     542.00\n"
     ]
    }
   ],
   "source": [
    "conta.saque(358)\n",
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "blind-happiness",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:    1216.00\n"
     ]
    }
   ],
   "source": [
    "conta.deposito(674)\n",
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "mature-industry",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:    1216.00\n"
     ]
    }
   ],
   "source": [
    "conta.saque(2000)\n",
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "anticipated-damage",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 234.567-01. Saldo:     316.00\n"
     ]
    }
   ],
   "source": [
    "conta.saque(900)\n",
    "conta.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "brazilian-albuquerque",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extrato CC No 234.567-01\n",
      "\n",
      "DEPÓSITO      1000.00\n",
      "SAQUE          100.00\n",
      "SAQUE          358.00\n",
      "DEPÓSITO       674.00\n",
      "SAQUE          900.00\n",
      "\n",
      "    Saldo:     316.00\n",
      "\n"
     ]
    }
   ],
   "source": [
    "conta.extrato()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "different-sleeping",
   "metadata": {},
   "source": [
    "### Exercício 6\n",
    "Altere o programa de forma que a mensagem saldo insuficiente seja exibida caso haja tentativa de sacar mais dinheiro que o saldo disponível"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "royal-assumption",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "israeli-lecture",
   "metadata": {},
   "source": [
    "### Exercício 7\n",
    "Modifique o método `resumo` da class `Conta` para exibir o nome e o telefone de cada cliente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "average-research",
   "metadata": {},
   "outputs": [],
   "source": [
    "from clientes import Cliente\n",
    "from bancos import Banco\n",
    "from contas import Conta\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "weekly-asthma",
   "metadata": {},
   "outputs": [],
   "source": [
    "bozo = Cliente(\"Bozo Palhaço\", \"236-0873\")\n",
    "vovó = Cliente(\"Vovó Mafalda\", \"236-0873\")\n",
    "josé = Cliente(\"José Vargas\", \"3866-1234\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "familiar-assignment",
   "metadata": {},
   "outputs": [],
   "source": [
    "contaBV = Conta([bozo, vovó], 1, 100)\n",
    "contaJ = Conta([josé], 2, 50)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "separated-helping",
   "metadata": {},
   "outputs": [],
   "source": [
    "tatu = Banco(\"Tatú\")\n",
    "tatu.abre_conta(contaBV)\n",
    "tatu.abre_conta(contaJ)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "found-eleven",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 1. Saldo:     100.00\n",
      "CC Número: 2. Saldo:      50.00\n"
     ]
    }
   ],
   "source": [
    "tatu.lista_contas()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "intellectual-identity",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "flush-observation",
   "metadata": {},
   "source": [
    "## Herança\n",
    "\n",
    "Herança é um recurso da programação orientada por objetos que permite reutilizar código, modificando sua característica"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "jewish-calibration",
   "metadata": {},
   "outputs": [],
   "source": [
    "from contas import ContaEspecial"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "exciting-alexandria",
   "metadata": {},
   "outputs": [],
   "source": [
    "bozo = Cliente(\"Bozo Palhaço\", \"236-0873\")\n",
    "vovó = Cliente(\"Vovó Mafalda\", \"236-0873\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "fancy-adams",
   "metadata": {},
   "outputs": [],
   "source": [
    "conta1 = Conta([\"bozo\"], 1, 1000)\n",
    "conta2 = ContaEspecial([vovó, bozo], 2, 500, 1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "intermediate-princess",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 1. Saldo:     950.00\n"
     ]
    }
   ],
   "source": [
    "conta1.saque(50)\n",
    "conta1.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "tender-collaboration",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 2. Saldo:     800.00\n"
     ]
    }
   ],
   "source": [
    "conta2.deposito(300)\n",
    "conta2.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "unsigned-cattle",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 1. Saldo:     760.00\n"
     ]
    }
   ],
   "source": [
    "conta1.saque(190)\n",
    "conta1.resumo()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "special-convert",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 2. Saldo:     895.15\n"
     ]
    }
   ],
   "source": [
    "conta2.deposito(95.15)\n",
    "conta2.resumo()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "personalized-preservation",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CC Número: 2. Saldo:    -604.85\n"
     ]
    }
   ],
   "source": [
    "conta2.saque(1500)\n",
    "conta2.resumo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "everyday-essence",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extrato CC No 1\n",
      "\n",
      "DEPÓSITO      1000.00\n",
      "SAQUE           50.00\n",
      "SAQUE          190.00\n",
      "\n",
      "    Saldo:     760.00\n",
      "\n"
     ]
    }
   ],
   "source": [
    "conta1.extrato()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "foreign-mattress",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extrato CC No 2\n",
      "\n",
      "DEPÓSITO       500.00\n",
      "DEPÓSITO       300.00\n",
      "DEPÓSITO        95.15\n",
      "SAQUE         1500.00\n",
      "\n",
      "    Saldo:    -604.85\n",
      "\n"
     ]
    }
   ],
   "source": [
    "conta2.extrato()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "occasional-banks",
   "metadata": {},
   "source": [
    "### Exercício 8\n",
    "Modofique as classes `Conta` e `ContaEspecial` para que a operação de saque retorne verdadeiro se o saque foi realizado e false caso contrário"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bronze-elevation",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "municipal-queensland",
   "metadata": {},
   "source": [
    "### Exercício 9\n",
    "Modifique a class `ContaEspecial` de forma que seu extrato exiba o limite e o total disponível para saque."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "optical-campaign",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "basic-reaction",
   "metadata": {},
   "source": [
    "## Desenvolvendo uma classe para controlar listas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "operational-belfast",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ListaUnica:\n",
    "    def __init__(self, elem_class):\n",
    "        self.lista = []\n",
    "        self.elem_class = elem_class\n",
    "    def __len__(self):\n",
    "        return len(self.lista)\n",
    "    def __iter__(self):\n",
    "        return iter(self.lista)\n",
    "    def __getitem__(self, p):\n",
    "        return self.lista[p]\n",
    "    def indiceValido(self, i):\n",
    "        return i >= 0 and i < len(self.lista)\n",
    "    def adiciona(self, elem):\n",
    "        if self.pesquisa(elem) == -1:\n",
    "            self.lista.append(elem)\n",
    "    def remove(self, elem):\n",
    "        self.lista.remove(elem)\n",
    "    def pesquisa(self, elem):\n",
    "        self.verifica_tipo(elem)\n",
    "        try:\n",
    "            return self.lista.index(elem)\n",
    "        except ValueError:\n",
    "            return -1\n",
    "    def verifica_tipo(self, elem):\n",
    "        if not isinstance(elem, self.elem_class):\n",
    "            raise TypeError(\"Tipo inválido\")\n",
    "    def ordena(self, chave=None):\n",
    "        self.lista.sort(key=chave)\n",
    "                         \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "further-marijuana",
   "metadata": {},
   "outputs": [],
   "source": [
    "lu = ListaUnica(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "sublime-science",
   "metadata": {},
   "outputs": [],
   "source": [
    "lu.adiciona(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "antique-consciousness",
   "metadata": {},
   "outputs": [],
   "source": [
    "lu.adiciona(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "freelance-honor",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "Tipo inválido",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_41173/78436172.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlu\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madiciona\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2.5\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_41173/263908826.py\u001b[0m in \u001b[0;36madiciona\u001b[0;34m(self, elem)\u001b[0m\n\u001b[1;32m     12\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mi\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mi\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlista\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     13\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0madiciona\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0melem\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---> 14\u001b[0;31m         \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpesquisa\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\u001b[0m\u001b[0;34m)\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[1;32m     15\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlista\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0melem\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/tmp/ipykernel_41173/263908826.py\u001b[0m in \u001b[0;36mpesquisa\u001b[0;34m(self, elem)\u001b[0m\n\u001b[1;32m     17\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlista\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\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;32mdef\u001b[0m \u001b[0mpesquisa\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0melem\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---> 19\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mverifica_tipo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\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     20\u001b[0m         \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     21\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlista\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/tmp/ipykernel_41173/263908826.py\u001b[0m in \u001b[0;36mverifica_tipo\u001b[0;34m(self, elem)\u001b[0m\n\u001b[1;32m     24\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mverifica_tipo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0melem\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[1;32m     25\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melem\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0melem_class\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---> 26\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Tipo inválido\"\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     27\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mordena\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchave\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[1;32m     28\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlista\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msort\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mchave\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: Tipo inválido"
     ]
    }
   ],
   "source": [
    "lu.adiciona(2.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "cardiac-pepper",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(lu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "prostate-allah",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "for e in lu:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "economic-appliance",
   "metadata": {},
   "outputs": [],
   "source": [
    "lu.adiciona(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "intended-poverty",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(lu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "chinese-waterproof",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lu[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "excellent-bonus",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lu[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "opponent-missouri",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "139760455345056"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(lu)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "superb-american",
   "metadata": {},
   "source": [
    "Outro exemplo com métodos \"mágicos\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "editorial-broadcast",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Nome:\n",
    "    def __init__(self, nome):\n",
    "        if nome is None or not nome.strip():\n",
    "            raise ValueError(\"Nome não pode ser nulo nem um branco\")\n",
    "        self.nome = nome\n",
    "        self.chave = nome.strip().lower()\n",
    "    def __str__(self):\n",
    "        return self.nome\n",
    "    def __repr__(self):\n",
    "        return f\"<Classe {type(self).__name__} em 0x{id(self):x} Nome: {self.nome} Chave: {self.chave}>\"\n",
    "    def __eq__(self, outro):\n",
    "        print(\"__eq__ Chamado\")\n",
    "        return self.nome == outro.nome\n",
    "    def __lt__(self, outro):\n",
    "        print(\"__lt__ Chamado\")\n",
    "        return self.nome < outro.nome\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "yellow-locking",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "spatial-shopper",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Nilo\n"
     ]
    }
   ],
   "source": [
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "japanese-contractor",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Nome não pode ser nulo nem um branco",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_41173/1734329681.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mB\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mNome\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[0m",
      "\u001b[0;32m/tmp/ipykernel_41173/3332852593.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, nome)\u001b[0m\n\u001b[1;32m      2\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnome\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[1;32m      3\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mnome\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrip\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----> 4\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Nome não pode ser nulo nem um branco\"\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      5\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnome\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchave\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\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;31mValueError\u001b[0m: Nome não pode ser nulo nem um branco"
     ]
    }
   ],
   "source": [
    "B = Nome(\"  \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "binary-butterfly",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Nome não pode ser nulo nem um branco",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_41173/3476832770.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mC\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mNome\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[0m\n\u001b[0m",
      "\u001b[0;32m/tmp/ipykernel_41173/3332852593.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, nome)\u001b[0m\n\u001b[1;32m      2\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnome\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[1;32m      3\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mnome\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrip\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----> 4\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Nome não pode ser nulo nem um branco\"\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      5\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnome\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchave\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnome\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstrip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\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;31mValueError\u001b[0m: Nome não pode ser nulo nem um branco"
     ]
    }
   ],
   "source": [
    "C = Nome(None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "extreme-france",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__eq__ Chamado\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A == Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "sexual-detroit",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__eq__ Chamado\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A != Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "intended-armor",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__lt__ Chamado\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A < Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "statutory-istanbul",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__lt__ Chamado\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A > Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "actual-kelly",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'>=' not supported between instances of 'Nome' and 'Nome'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_41173/816388600.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mNome\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Nilo\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: '>=' not supported between instances of 'Nome' and 'Nome'"
     ]
    }
   ],
   "source": [
    "A >= Nome(\"Nilo\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "global-accuracy",
   "metadata": {},
   "source": [
    "## Criando exceções\n",
    "\n",
    "Podemos criar novos tipos de exceção para diferenciar os erros gerados nos nossos programas.\n",
    "\n",
    "\n",
    "Para isso, é é necessário extender a class **`Exception`**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "sunrise-palestine",
   "metadata": {},
   "outputs": [],
   "source": [
    "class NovaException(Exception):\n",
    "    pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "marked-threshold",
   "metadata": {},
   "outputs": [],
   "source": [
    "def lançar_erro():\n",
    "    raise NovaException\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "breeding-breath",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Uma excecão de tipo NovaExceção foi lançada\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    lançar_erro()\n",
    "except NovaException as n:\n",
    "    print(\"Uma excecão de tipo NovaExceção foi lançada\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "packed-shore",
   "metadata": {},
   "source": [
    "As exceções podem ter informações ou atributos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "fossil-refund",
   "metadata": {},
   "outputs": [],
   "source": [
    "class EstoqueException(Exception):\n",
    "    def __init__(self, mensagem, codigo_de_erro):\n",
    "        super().__init__(mensagem)\n",
    "        self.codigo_de_erro = codigo_de_erro"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "relative-touch",
   "metadata": {},
   "outputs": [],
   "source": [
    "def verifique_quantidade(quantidade):\n",
    "    if quantidade < 0:\n",
    "        raise EstoqueException(\"Quantidade negativa\", codigo_de_erro=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "sacred-update",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Erro: 1 Quantidade negativa\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    verifique_quantidade(-10)\n",
    "except EstoqueException as ee:\n",
    "    print(f\"Erro: {ee.codigo_de_erro} {ee}\")\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fundamental-homeless",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "abstract-candle",
   "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
}
