{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Uma calculadora poderosa \n", "\n", "O prompt do Python e o Ciclo Ler-Avaliar-Imprimir (LAI) \n", "---------------------------------------------\n", "\n", "Python é uma linguagem *interpretada*. Podemos coletar sequencias de comandos em texto e salvá-los em um arquivo como um *programa Python*. A convenção é que estes arquivos tenham a extensão `.py`, como, por exemplo, `hello.py`.\n", "\n", "Podemos também entrar com comandos individuais no `prompt` Python que são imediatamente avaliados e executados pelo interpretador Python. Isto é muito útil para o programador/aprendiz entender como usar certos comandos e depois estendê-los para obter um programa maior. O papel da linguagem Python pode ser descrito como segue: *Ler* o comando, *Avaliar* este comando, *Imprimir* o valor avaliado e repetir o ciclo (*loop*) - isto dá origem à abreviatura LAI. O *prompt* Python é um terminal básico onde você introduz comandos após o marcador `>>>`, como no exemplo a seguir: \n", "\n", " >>> 2 + 2\n", " 4\n", "\n", "A interface LAI que estamos usando é um *notebook Jupyter*. Blocos de código aparecem com um `In` à esquerda deles." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "4 + 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para editar o código, clique na área de código (célula). Uma borda verde indica que a célula está selecionada (consulte o menu de ajuda, `Help`, do Jupyter Notebook para saber mais sobre os modos de *comando* e *edição*). Em seguida, pressione `shift-enter`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calculadora\n", "----------\n", "\n", "Operações básicas tais como adição (`+`), subtração (`-`), multiplicação (`*`), divisão (`/`) e exponenciação (`**`) funcionam (na maioria das vezes) como esperado:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10010" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 + 10000" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "40.5" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "42 - 1.5" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "517" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "47 * 11" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "20.0" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 / 0.5" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**2 # O operador de exponenciação ('à potência de') é **, e NÃO ^" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**3" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**4" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 + 2" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Linhas começando com a tralha (#) indicam um comentário\n", "2 + 2" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 + 2 # é um comentário na mesma linha de código" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "e, usando o fato que $\\sqrt[n]{x} = x^{1/n}$, podemos computar $\\sqrt{3} = 1.732050\\dots$ usando `**`:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.7320508075688772" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3**0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parentêses podem ser usados para agrupamento:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "25" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * 10 + 5" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * (10 + 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Divisão inteira\n", "----------------\n", "\n", "Em Python 3, a divisão funciona como você esperaria:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2.5" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "15/6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Em Python 2, no entanto, `15/6` retornará `2`.\n", "\n", "\n", "Este fenômeno é conhecido (em muitas linguages de programação, incluindo C) como *divisão inteira*: pelo fato de termos fornecido dois números inteiros (`15` e `6`) para o operador de divisão, a hipótese é que o valor de retorno seja também do tipo inteiro. A resposta matematicamente correta é um número em ponto flutuante. \n", "\n", "A convenção para divisão inteira é truncar os dígitos fracionários e retornar a parte inteira apenas (i.e., `2` neste exemplo). Ela também pode ser chamada de \"divisão por baixo\" (*floor division*).\n", "\n", "\n", "### Como evitar a divisão inteira\n", "\n", "Há duas maneiras de evitar o problema da divisão inteira:\n", "\n", "1. Use o estilo de divisão do Python 3: isto está disponível mesmo no Python 2 com uma declaração especial de importação:\n", "\n", " ```python\n", " >>> from __future__ import division\n", " >>> 15/6\n", " 2.5\n", " ```\n", "\n", "Caso você queira usar `from __future__ import division` em um programa Python, a declaração seria incluída normalmenteno no início do arquivo.\n", "\n", "2. Alternativamente, se você assegurar que, pelo menos um número (numerador ou denominador) seja do tipo `float` (ou `complex`), o operador de divisão retornará um número em ponto flutuante. Isto pode ser feito escrevendo `15.` em vez de `15`, ou forçando a conversão do número para `float`, i.e. usando `float(15)` em vez de, simplesmente, `15`:\n", "\n", " ```python\n", " >>> 15./6\n", " 2.5\n", " >>> float(15)/6\n", " 2.5\n", " >>> 15/6.\n", " 2.5\n", " >>> 15/float(6)\n", " 2.5\n", " >>> 15./6.\n", " 2.5\n", " ```\n", "\n", "Se você realmente quiser a divisão inteira, poderá usar `//`. Por exemplo, `1//2` retornará `0` tanto em Python 2 quanto em Python 3." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Por que devo me importar com este problema de divisão?\n", "\n", "A divisão inteira pode resultar em problemas surpreendentes: suponha que você esteja escrevendo código para calcular a média $m = (x + y)/2$ de dois números $x$ e $y$. A primeira tentativa de escrever isto pode ser dada como:\n", "\n", "```python\n", "m = (x + y) / 2\n", "```\n", "\n", "Suponha que isto seja testado com $x = 0.5$, $y = 0.5$. Então, a linha acima computaria a resposta correta $m  = 0.5$ (porque `0.5 + 0.5 = 1.0`, i.e. 1.0 é um número de ponto flutuante, e assim `1.0/2` seria avaliado como `0.5`). Além disso, poderíamos usar $x = 10$, $y  = 30$, e porque `10 + 30 = 40` e `40/2` seria `20`, obtemos a resposta correta $m = 20$. Entretanto, se tentássemos com os inteiros $x  = 0$ e $y = 1$, então o código retornaria $m  = 0$ (porque `0 + 1 = 1` e `1/2` seria avaliado como `0`), quando, na verdade, $m = 0.5$ seria a resposta correta.\n", "\n", "Temos muitas possibilidades para fazer a linha de código acima funcionar seguramente, incluindo estas três formas:\n", "```python\n", "m = (x + y) / 2.0\n", "\n", "m = float(x + y) / 2\n", "\n", "m = (x + y) * 0.5\n", "```\n", "\n", "Este comportamento de divisão inteira é comum entre a maioria das linguagens de programação (incluindo as importantes C, C++ e Fortran). Portanto, devemos estar cientes deste fato.\n", "\n", "Funções matemáticas\n", "----------------------\n", "\n", "Pelo fato de Python ser uma linguagem de programação com propósitos gerais, funções matemáticas comumente usadas, tais como seno, cosseno, exponencial, logaritmo e muitas outras, estão localizadas no módulo de matemática chamado `math`. Podemos fazer uso delas assim que importarmos este módulo. Por exemplo:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2.718281828459045" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "math.exp(1.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Usando a função `dir`, podemos listar o diretório de objetos disponíveis no módulo `math`:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__doc__',\n", " '__file__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " 'acos',\n", " 'acosh',\n", " 'asin',\n", " 'asinh',\n", " 'atan',\n", " 'atan2',\n", " 'atanh',\n", " 'ceil',\n", " 'copysign',\n", " 'cos',\n", " 'cosh',\n", " 'degrees',\n", " 'e',\n", " 'erf',\n", " 'erfc',\n", " 'exp',\n", " 'expm1',\n", " 'fabs',\n", " 'factorial',\n", " 'floor',\n", " 'fmod',\n", " 'frexp',\n", " 'fsum',\n", " 'gamma',\n", " 'gcd',\n", " 'hypot',\n", " 'inf',\n", " 'isclose',\n", " 'isfinite',\n", " 'isinf',\n", " 'isnan',\n", " 'ldexp',\n", " 'lgamma',\n", " 'log',\n", " 'log10',\n", " 'log1p',\n", " 'log2',\n", " 'modf',\n", " 'nan',\n", " 'pi',\n", " 'pow',\n", " 'radians',\n", " 'sin',\n", " 'sinh',\n", " 'sqrt',\n", " 'tan',\n", " 'tanh',\n", " 'tau',\n", " 'trunc']" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(math)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como de costume, a função `help` pode fornecer mais informação acerca do módulo (use `help(math)`) ou de objetos individuais: " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function exp in module math:\n", "\n", "exp(...)\n", " exp(x)\n", " \n", " Return e raised to the power of x.\n", "\n" ] } ], "source": [ "help(math.exp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O módulo de matemática define as constantes $\\pi$ and $e$:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.141592653589793" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.pi" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2.718281828459045" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.e" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-1.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.cos(math.pi)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.log(math.e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variáveis\n", "---------\n", "\n", "Uma *variável* pode ser usada para armazenar um certo valor ou objeto. Em Python, todos os números (e todas as outras coisas mais, incluindo funções, módulos e arquivos) são objetos. Uma variável é criada por atribuição:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = 0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma vez que a variável `x` tiver sido criada através da atribuição de 0.5 neste exemplo, podemos fazer uso dela:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.5" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x*3" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.25" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x**2" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "333" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = 111\n", "y + 222" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Uma variável é substituída se um novo valor for atribuído a ela:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.0000000000000002" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = 0.7\n", "math.sin(y) ** 2 + math.cos(y) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O sinal de igual (`=`) é usado para atribuir um valor à uma variável." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "900" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "largura = 20\n", "altura = 5 * 9\n", "largura * altura" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um valor pode ser atribuído a várias variáveis simultaneamente:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = y = z = 0 # inicializa x, y e z com 0\n", "x" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variáveis devem ser criadas com atribuição de valor antes de serem usadas, senão um erro ocorrerá:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'n' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# tenta acessar uma variável indefinada\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'n' is not defined" ] } ], "source": [ "# tenta acessar uma variável indefinada\n", "n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Em modo interativo, a última expressão impressa é atribuída à variável `_`. Isto significa que quando você está usando Python como uma calculadora de mesa, é um tanto fácil continuar os cálculos. Por exemplo:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "12.5625" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "taxa = 12.5 / 100\n", "preco = 100.50\n", "preco * taxa" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "113.0625" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "preco + _" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esta variável deve ser tratada como \"somente leitura\" pelo usuário. Não atribua, explicitamente, um valor a ela - você criaria uma variável local independente com o mesmo nome assim mascarando o comportamento \"mágico\" da variável pré-construída.\n", "\n", "### Terminologia\n", "\n", "Estritamente falando, o seguinte acontece quando escrevemos algo como:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = 0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Primeiro, o Python cria o objeto `0.5`. Tudo em Python é um objeto, e assim o é o número em ponto flutuante 0.5. Este objeto é armazenado em algum lugar na memória. Em seguida, o Python *vincula um nome ao objeto*. O nome é `x`, e nos referimos a `x` casual e frequentemente como uma variável, um objeto, ou mesmo o valor 0.5. Entretanto, tecnicamente, `x` é um nome que é limitado ao objeto `0.5`. Outro modo de dizer isto é que `x` é uma *referência* para o objeto.\n", "\n", "Enquanto é frequentemente suficiente pensar em atribuir 0.5 à uma variável `x`, existem situações nas quais precisamos lembrar o que realmente ocorre. Em particular, quando passamos referências de objetos para funções, precisamos ter em mente que a função pode operar sobre o objeto (em vez de uma cópia do objeto).\n", "\n", "Equações impossíveis\n", "--------------------\n", "\n", "Em programas computacionais, frequentemente encontramos declarações como" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = x + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se lêssemos esta equação do modo como estamos acostumados da matemática, poderíamos subtrair $x$ de ambos os lados de $x = x + 1$ para descobrir que $0 = 1$. Todavia, sabemos que isto não é verdadeiro. Então, algo está errado aqui...\n", "\n", "A resposta é que \"equações“ em códigos computacionais não são realmente equações, mas *atribuições*. Elas tem de ser lidas em dois passos:\n", "\n", "1. Avaliando o valor no membro direito do sinal de igual;\n", "\n", "2. Atribuindo este valor à variável cujo nome é mostrado no membro esquerdo. (Em Python: vincula-se o nome à esquerda ao objeto mostrado à direita).\n", "\n", "Na literatura de ciência da computação, a notação seguinte é usada para expressar atribuições a fim de se evitar confusão com equações matemáticas:\n", "\n", "$$x \\leftarrow x + 1$$\n", "\n", "Vamos aplicar a nossa regra de dois passos à atribuição `x = x + 1` dada acima:\n", "\n", "1. Avalie o valor no membro direito do sinal de igual: para isto, precisamos saber o valor atual de `x`. Assumamos que o valor atual de `x` é `4`. Neste caso, o membro direito, `x+1` é avaliado para `5`.\n", "\n", "2. Atribua este valor (i.e. `5`) à variável cujo nome é mostrado no membro esquerdo (`x`).\n", "\n", "Confirmemos com o *prompt* do Python que esta é a interpretação correta:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 4 \n", "x = x + 1\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A notação `+=` \n", "\n", "Por ser uma operação bastante comum aumentar uma variável `x` por alguma quantidade fixa `c`, podemos escrevê-la como: \n", "\n", "```python\n", "x += c\n", "```\n", "\n", "em vez de\n", "\n", "```python\n", "x = x + c\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nosso exemplo inicial acima poderia, assim, ter sido escrito como:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 4\n", "x += 1\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Os mesmos operadores são definidos para multiplicação por uma constante (`*=`), subtração de uma constante (`-=`) e divisão por uma constante (`/=`).\n", "\n", "Note que a ordem de `+` e `=` importa:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 1\n", "x += 4\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "aumentará a variável `x` de um, ao passo que" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x =+ 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "atribuirá o valor `+1` à variável `x`." ] } ], "metadata": { "celltoolbar": "Edit Metadata", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 1 }