├── Avatar.png ├── src ├── site-icon.png ├── gatsby-theme-document │ └── logo.mdx └── gatsby-plugin-theme-ui │ ├── components.js │ ├── headings.js │ ├── colors.js │ └── index.js ├── README.md ├── package.json ├── content ├── index.mdx ├── while-loops.mdx ├── input.mdx ├── iteradores.mdx ├── for-loops.mdx ├── geradores.mdx ├── ambiente.mdx ├── sets.mdx ├── expressoes-lambda.mdx ├── numeros.mdx ├── if-else.mdx ├── tipos-variaveis.mdx ├── tuplas.mdx ├── dicionarios.mdx ├── operadores.mdx ├── sintaxe.mdx ├── xml.mdx ├── json.mdx ├── decoradores.mdx ├── ambientes-virtuais.mdx ├── introducao.mdx ├── expressoes-regulares.mdx └── modulos.mdx ├── .gitignore └── gatsby-config.js /Avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/pythoniluminado/master/Avatar.png -------------------------------------------------------------------------------- /src/site-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/the-akira/pythoniluminado/master/src/site-icon.png -------------------------------------------------------------------------------- /src/gatsby-theme-document/logo.mdx: -------------------------------------------------------------------------------- 1 | Python Iluminado 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/gatsby-plugin-theme-ui/components.js: -------------------------------------------------------------------------------- 1 | import Prism from '@theme-ui/prism'; 2 | export default { 3 | pre: props => props.children, 4 | code: Prism 5 | }; 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | pythoniluminado.netlify.app 3 |

4 | 5 |

6 | akira
7 |

8 | 9 |

10 | Código fonte do website do projeto Python Iluminado 11 |

12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-theme-document-example", 3 | "author": "Code Bushi", 4 | "repository": "https://github.com/codebushi/gatsby-theme-document-example", 5 | "version": "1.0.0", 6 | "license": "MIT", 7 | "scripts": { 8 | "develop": "gatsby develop", 9 | "build": "gatsby build" 10 | }, 11 | "dependencies": { 12 | "gatsby": "^2.15.9", 13 | "gatsby-theme-document": "1.0.8", 14 | "react": "^16.9.0", 15 | "react-dom": "^16.9.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /content/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python Iluminado" 3 | description: "Guia para iniciantes com programação!" 4 | --- 5 | 6 | ![img](https://raw.githubusercontent.com/the-akira/pythoniluminado/master/Avatar.png) 7 | 8 | Python Iluminado é um Guia construído especialmente para Iniciantes com a Linguagem Python. O objetivo é explorar conceitos fundamentais de programação e compreender o funcionamento da linguagem e suas capacidades e potencial, bem como apresentar uma vasta lista de materiais de estudos qualificados para você ampliar e aperfeiçoar o seu conhecimento. 9 | -------------------------------------------------------------------------------- /src/gatsby-plugin-theme-ui/headings.js: -------------------------------------------------------------------------------- 1 | const headingBase = { 2 | fontFamily: 'heading', 3 | lineHeight: 'heading', 4 | fontWeight: 'heading', 5 | mt: 0, 6 | mb: 3, 7 | '::before': { 8 | content: '" "', 9 | display: 'block', 10 | paddingTop: 30, 11 | marginBottom: 40, 12 | borderBottom: '1px solid', 13 | borderBottomColor: 'borderColor' 14 | } 15 | }; 16 | 17 | export default { 18 | h1: { 19 | ...headingBase, 20 | fontSize: 5 21 | }, 22 | h2: { 23 | ...headingBase, 24 | fontSize: 4 25 | }, 26 | h3: { 27 | ...headingBase, 28 | fontSize: 3 29 | }, 30 | h4: { 31 | ...headingBase, 32 | fontSize: 2 33 | }, 34 | h5: { 35 | ...headingBase, 36 | fontSize: 1 37 | }, 38 | h6: { 39 | ...headingBase, 40 | fontSize: 0 41 | }, 42 | img: { 43 | maxWidth: '100%', 44 | height: 'auto', 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/gatsby-plugin-theme-ui/colors.js: -------------------------------------------------------------------------------- 1 | export default { 2 | text: "#000", 3 | background: "#fff", 4 | primary: "#e63b19", 5 | secondary: "#c70d3a", 6 | sidebar: "#eee", 7 | borderColor: "rgba(0, 0, 0, 0.15)", 8 | modes: { 9 | dark: { 10 | text: "#fff", 11 | background: "#182952", 12 | primary: "#f638dc", 13 | secondary: "#ff7976", 14 | sidebar: "#101d3c", 15 | borderColor: "rgba(255, 255, 255, 0.15)" 16 | }, 17 | cool: { 18 | text: "#fff", 19 | background: "#05386b", 20 | primary: "#5cdb95", 21 | secondary: "#bef992", 22 | sidebar: "#052e56", 23 | borderColor: "rgba(255, 255, 255, 0.15)" 24 | }, 25 | deep: { 26 | text: "#fff", 27 | background: "hsl(230,25%,18%)", 28 | primary: "hsl(260, 100%, 80%)", 29 | secondary: "hsl(290, 100%, 80%)", 30 | sidebar: "hsla(230, 20%, 0%, 20%)", 31 | borderColor: "rgba(255, 255, 255, 0.15)" 32 | } 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env.production 2 | .env.development 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | package.lock 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # gatsby files 62 | .cache/ 63 | public 64 | 65 | # Mac files 66 | .DS_Store 67 | 68 | # Yarn 69 | yarn-error.log 70 | .pnp/ 71 | .pnp.js 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | yarn.lock -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Python Iluminado`, 4 | name: `Gabriel Felippe`, 5 | siteUrl: `https://github.com/the-akira/Python-Iluminado`, 6 | description: `Guia para Iniciantes com a Linguagem Python`, 7 | social: [ 8 | { 9 | name: `github`, 10 | url: `https://github.com/the-akira` 11 | }, 12 | { 13 | name: `twitter`, 14 | url: `https://twitter.com/akirascientist` 15 | } 16 | ], 17 | sidebarConfig: { 18 | forcedNavOrder: [ 19 | "introducao", 20 | "ambiente", 21 | "sintaxe", 22 | "tipos-variaveis", 23 | "numeros", 24 | "strings", 25 | "operadores", 26 | "listas", 27 | "tuplas", 28 | "dicionarios", 29 | "sets", 30 | "input", 31 | "if-else", 32 | "for-loops", 33 | "while-loops", 34 | "funcoes", 35 | "expressoes-lambda", 36 | "modulos", 37 | "input-output-arquivos", 38 | "erros-excecoes-testes", 39 | "data-tempo", 40 | "classes-objetos", 41 | "expressoes-regulares", 42 | "json", 43 | "xml", 44 | "iteradores", 45 | "geradores", 46 | "decoradores", 47 | "ambientes-virtuais", 48 | "mysql", 49 | "mongodb", 50 | "grandes-bibliotecas", 51 | "referencias-online" 52 | ], 53 | ignoreIndex: true 54 | } 55 | }, 56 | plugins: [{ resolve: `gatsby-theme-document` }] 57 | }; 58 | -------------------------------------------------------------------------------- /src/gatsby-plugin-theme-ui/index.js: -------------------------------------------------------------------------------- 1 | import nightOwl from "@theme-ui/prism/presets/night-owl.json"; 2 | import colors from "./colors"; 3 | import headings from "./headings"; 4 | 5 | const transition = "0.2s ease-out"; 6 | const systemFonts = 7 | "-apple-system, BlinkMacSystemFont, San Francisco, Helvetica Neue, Helvetica, Ubuntu, Roboto, Noto, Segoe UI, Arial, sans-serif"; 8 | 9 | export default { 10 | initialColorMode: `dark`, 11 | colors, 12 | fonts: { 13 | body: systemFonts, 14 | heading: systemFonts, 15 | monospace: "Menlo, monospace" 16 | }, 17 | fontSizes: [12, 14, 16, 24, 28, 36, 48, 64], 18 | fontWeights: { 19 | body: 400, 20 | heading: 700, 21 | bold: 700 22 | }, 23 | lineHeights: { 24 | body: 1.5, 25 | heading: 1.125 26 | }, 27 | letterSpacings: { 28 | body: "normal", 29 | caps: "0.2em" 30 | }, 31 | breakpoints: [ 32 | ["phone_small", 320], 33 | ["phone", 376], 34 | ["phablet", 540], 35 | ["tablet", 735], 36 | ["desktop", 1070], 37 | ["desktop_medium", 1280], 38 | ["desktop_large", 1440] 39 | ], 40 | transition, 41 | styles: { 42 | root: { 43 | fontFamily: "body", 44 | lineHeight: "body", 45 | fontWeight: "body", 46 | ...headings 47 | }, 48 | ...headings, 49 | p: { 50 | my: 4 51 | }, 52 | a: { 53 | color: "secondary", 54 | transition: `color ${transition}`, 55 | ":hover,:focus": { 56 | color: "text" 57 | } 58 | }, 59 | pre: { 60 | ...nightOwl, 61 | fontFamily: `"Operator Mono", monospace`, 62 | fontSize: "0.9rem", 63 | tabSize: 4, 64 | hyphens: `none`, 65 | overflow: `auto`, 66 | borderRadius: 6, 67 | p: 3, 68 | my: 4 69 | }, 70 | inlineCode: { 71 | color: `primary`, 72 | background: `rgba(233, 218, 172, 0.15)`, 73 | borderRadius: 3, 74 | px: `0.4rem`, 75 | py: `0.2rem` 76 | }, 77 | table: { 78 | width: "100%", 79 | borderCollapse: "separate", 80 | borderSpacing: 0 81 | }, 82 | th: { 83 | textAlign: "left", 84 | borderBottomStyle: "solid" 85 | }, 86 | td: { 87 | textAlign: "left", 88 | borderBottomStyle: "solid" 89 | } 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /content/while-loops.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'While Loops' 3 | description: 'Aprenda sobre While Loops' 4 | --- 5 | 6 | O **while loop** em **Python** é utilizado para iterar em cima de um bloco de código enquanto determinada **Expressão de Teste** (condição) for avaliada como **True**. 7 | 8 | **While** é normalmente usado quando não sabemos de ante-mão o número de vezes no qual vamos iterar. 9 | 10 | Python primeiro verifica a condição: 11 | 12 | - Se for **False**, o loop será encerrado e o controle será passado para a próxima instrução após o corpo do While Loop. 13 | - Se a condição for **True**, o corpo do While Loop será executado e a condição será verificada novamente. 14 | 15 | Este procedimento continua enquanto a condição for **True**. Quando a condição se torna **False**, o loop termina e o controle é passado para a próxima instrução após o loop. 16 | 17 | ### Estrutura Básica do While 18 | 19 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/WhileLoop.png) 20 | 21 | ``` 22 | while : 23 | 24 | 25 | ... 26 | ``` 27 | 28 | - `` é avaliado para um **booleano** 29 | - Se a `` for **True**, executa-se todas as `` dentro do bloco de código while 30 | - Checa a `` novamente 31 | - Repete até que a `` seja **False** 32 | 33 | Vejamos um exemplo prático: 34 | 35 | ```python 36 | i = 1 37 | while i < 10: 38 | print(i) 39 | i += 1 40 | ``` 41 | 42 | Observe que `i += 1` é o mesmo que `i = i + 1`, precisamos dessa expressão, caso contrário teremos um loop infinito. 43 | 44 | Também podemos definir o while loop em um único statement, da seguinte forma: 45 | 46 | ```python 47 | count = 0 48 | while (count < 5): count += 1; print("Hello World") 49 | ``` 50 | 51 | A palavra-chave **break** também pode ser utilizada em conjunto com o **while**: 52 | 53 | ```python 54 | a = 1 55 | while a < 10: 56 | print(a) 57 | if a == 5: 58 | break 59 | a += 1 60 | ``` 61 | 62 | Neste caso só serão impressos os números de 1 até 5, pois quando `a == 5` o loop irá encerrar. 63 | 64 | Podemos também usar a palavra-chave **continue**: 65 | 66 | ```python 67 | x = 0 68 | while x < 10: 69 | x += 1 70 | if x == 5: 71 | continue 72 | print(x) 73 | ``` 74 | 75 | Neste caso o número 5 não será impresso, pois quando `x == 5` o comando **print()** não será executado. 76 | 77 | O while loop também pode ser usado para computarmos a [Sequência de Fibonacci](https://en.wikipedia.org/wiki/Fibonacci): 78 | 79 | ```python 80 | n = int(input("Informe o número de termos: ")) 81 | 82 | a, b = 0, 1 83 | count = 0 84 | 85 | while count < n: 86 | print(a) 87 | c = a + b 88 | a, b = b, c 89 | count += 1 90 | ``` 91 | 92 | Com ele podemos facilmente definir o algoritmo de [Euclides](https://en.wikipedia.org/wiki/Euclid) para buscar o máximo divisor comum entre dois números: 93 | 94 | ```python 95 | def gcd(x, y): 96 | while y != 0: 97 | (x, y) = (y, x % y) 98 | return x 99 | 100 | print(gcd(155,70)) # 5 101 | print(gcd(77,33)) # 11 102 | print(gcd(400,140)) # 20 103 | print(gcd(97,13)) # 1 104 | ``` 105 | 106 | ### For vs While 107 | 108 | #### for 109 | 110 | - Número de iterações é **conhecido** 111 | - Pode finalizar antecipadamente através do **break** 112 | - Utiliza um **contador** 113 | 114 | #### while 115 | 116 | - Número de iterações **ilimitados** 117 | - Pode finalizar antecipadamente através do **break** 118 | - Pode utilizar um **contador**, porém é necessário inicializar ele antes do loop e incrementá-lo dentro do loop 119 | 120 | Como vimos, **while loops** não são muito misteriosos, porém a utilidade deles pode ser muito grande em nossos programas! 121 | -------------------------------------------------------------------------------- /content/input.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Input de Dados' 3 | description: 'Aprenda a coletar dados dos usuários' 4 | --- 5 | 6 | Desenvolvedores geralmente precisam interagir com os usuários, seja para obter dados ou fornecer algum tipo de resultado. A maioria dos programas hoje em dia usam uma caixa de diálogo como uma forma de solicitar ao usuário algum tipo de *input* (entrada) do usuário. 7 | 8 | Na maioria dos casos, o *input* vem do teclado. Para este propósito, Python fornece a função `input()`, que possui um parâmetro opcional, que é a string que será enviada para o usuário. 9 | 10 | Até então todos os nossos programas foram **estáticos**, os valores das variáveis foram definidos por nós no código fonte. De forma a aumentar nossas opções de criações, vamos então aprender como podemos coletar dados dos usuários. 11 | 12 | ### Exemplos Input 13 | 14 | Começaremos chamando a função `input()`, passando como argumento uma string que será retornada como feedback ao usuário e armazenaremos o valor digitado pelo usuário na variável `n` que será impressa na sequência. 15 | 16 | ```python 17 | n = input("Insira um número: ") 18 | print(n) 19 | ``` 20 | 21 | Ao executarmos o código acima, o prompt de comandos aguardará pela entrada de dados por parte de usuário, uma vez informado o valor e enviado, ele será impresso. Vamos agora ver qual o tipo de dados que temos em **n**: 22 | 23 | ```python 24 | print(type(n)) # 25 | ``` 26 | 27 | Como podemos ver, embora tenhamos digitado um **número**, ele nos retorno uma **string**, para obtermos um número podemos utilizar as funções **int()** ou **float()** para fazer a conversão. 28 | 29 | ```python 30 | n = int(input("Insira um número: ")) 31 | print(type(n)) # 32 | ``` 33 | 34 | O método **eval()** também é capaz de solucionar o nosso problema e até mesmo resolver expressões, muito útil, mas tenha cuidado com ele! 35 | 36 | ```python 37 | eval('2+3') # 5 38 | numero = eval(input("Digite um valor: ")) 39 | print(numero) # 2.3 40 | print(type(numero)) # 41 | ``` 42 | 43 | ### Pedra, Papel e Tesoura 44 | 45 | Uma vez que sabemos como coletar dados de usuários, podemos agora criar jogos. Neste exemplo vamos construir o clássico Pedra, Papel e Tesoura, também conhecido como Jankenpon. 46 | 47 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/JanKenPon.png) 48 | 49 | Para nos auxiliar neste pequeno projeto, vamos contar com a ajuda da função **choice()** da biblioteca [random](https://docs.python.org/3/library/random.html), ela será responsável por emular uma escolha pseudo-aleatória da máquina, entre as três opções disponíveis (Pedra, Papel e Tesoura). 50 | 51 | Também iremos utilizar um **While Loop** para manter o jogo executando até que o usuário deseje sair. 52 | 53 | Coletaremos o input do usuário através da função `input()` e testaremos uma série de `if`, `elif` e `else` para sabermos quem é o vitorioso. 54 | 55 | ```python 56 | from random import choice 57 | 58 | opcoes = ['pedra', 'papel', 'tesoura'] 59 | maquina = choice(opcoes) 60 | jogando = True 61 | 62 | while jogando: 63 | print("# pedra\n# papel\n# tesoura\n# sair") 64 | player = input('Escolha entre uma das opções: ') 65 | if maquina == player.lower(): 66 | print(f'Ocorreu um empate!') 67 | elif player.lower() == 'pedra': 68 | if maquina == 'papel': 69 | print(f'Você perdeu! {maquina} cobre {player.lower()}!') 70 | else: 71 | print(f'Parabéns! Você venceu! {player.lower()} quebra {maquina}!') 72 | elif player.lower() == 'papel': 73 | if maquina == 'tesoura': 74 | print(f'Você perdeu! {maquina} corta {player.lower()}!') 75 | else: 76 | print(f'Parabéns! Você venceu! {player.lower()} cobre {maquina}!') 77 | elif player.lower() == 'tesoura': 78 | if maquina == 'pedra': 79 | print(f'Você perdeu! {maquina} esmaga {player.lower()}!') 80 | else: 81 | print(f'Parabéns! Você venceu! {player.lower()} corta {maquina}!') 82 | elif player.lower() == 'sair': 83 | jogando = False 84 | else: 85 | print('Jogada inválida, verifique se digitou a opção corretamente!') 86 | print('-'*45) 87 | maquina = choice(opcoes) 88 | ``` 89 | 90 | Como podemos ver, a função **input()** pode nos auxiliar na questão de receber dados de usuários e através dos diversos métodos vistos, podemos converter os dados recebidos para trabalharmos com eles de forma adequada. 91 | -------------------------------------------------------------------------------- /content/iteradores.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Iteradores' 3 | description: 'Aprenda sobre Iteradores' 4 | --- 5 | 6 | Iteradores são objetos que podem ser iterados. Nesse guia vamos estudá-los e aprender como eles funcionam construindo um iterador usando os métodos `__iter__` e `__next__`. 7 | 8 | - Um objeto iterável é um objeto que implementa `__iter__`, que deve retornar um objeto iterador. 9 | - Um iterador é um objeto que implementa **next**, que deve retornar o próximo elemento do objeto iterável que o retornou e gerar uma exceção **StopIteration** quando não houver mais elementos disponíveis. 10 | 11 | ## Introdução 12 | 13 | **Iteradores** sempre estiveram conosco em Python, eles estão implementados nos **for loops**, **geradores**, etc, porém estão "escondidos". Um iterador é simplesmente um objeto que podemos iterar nele, ou seja, um objeto que retornará dados, um elemento de cada vez. 14 | 15 | O objeto iterador implementa dois métodos especiais `__iter__()` e `__next__()`, que são conhecidos como o protocolo do iterador. Um objeto é chamado de iterável se formos capazes de obter um iterador dele, estruturas como **lista**, **tupla** e **string** são iteráveis. A função **iter()** (que chama o método `__iter__`) retorna um iterador delas. 16 | 17 | Vamos então aos experimentos para entendermos melhor os iteradores, usaremos a função **next()** para iterar manualmente através de todos os itens de um iterador. Quando chegarmos ao fim e não houver mais dados para retorno, ocorrerá um erro **StopIteration**. 18 | 19 | ```python 20 | lista = [1,2,3,4] 21 | 22 | iterador = iter(lista) 23 | 24 | print(next(iterador)) # 1 25 | print(next(iterador)) # 2 26 | print(iterador.__next__()) # 3 27 | print(iterador.__next__()) # 4 28 | 29 | next(iterador) # Sem mais itens para iterar, erro StopIteration ocorre 30 | ``` 31 | 32 | Uma forma melhor e mais simples de iterar automaticamente seria usando um for loop. Usando ele, nós podemos iterar sob qualquer objeto que retorne um iterador, por exemplo uma lista, string, arquivo, etc. 33 | 34 | ```python 35 | for elemento in lista: 36 | print(lista) 37 | # 1 38 | # 2 39 | # 3 40 | # 4 41 | ``` 42 | 43 | Vimos que o **for** foi capaz de iterar automaticamente através da **lista**, agora vamos analisar como ele faz essa mágica internamente no Python: 44 | 45 | ```python 46 | for elemento in iteravel: 47 | # faça algo com o elemento 48 | ``` 49 | 50 | É na verdade: 51 | 52 | ```python 53 | # cria um objeto iterador do iteravel 54 | objeto_iteravel = iter(iteravel) 55 | 56 | # Loop infinito 57 | while True: 58 | try: 59 | # obtém o novo item 60 | elemento = next(objeto_iteravel) 61 | # faz algo com o elemento 62 | except StopIteration: 63 | # Se o StopIteration ocorrer, break no loop 64 | break 65 | ``` 66 | 67 | Veja que internamente o **for loop** cria um objeto iterador **objeto_iteravel** chamando o método **iter()** nele, e que na verdade ele é um **while loop**. Dentro desse while loop ele chama **next()** para pegar o próximo elemento e executar o for loop com esse valor, assim que todos os itens forem percorridos, StopIteration é acionado que é capturado internamente e o loop acaba, perceba que qualquer outra exceção irá passar. 68 | 69 | ## Criando um Iterador 70 | 71 | Para criar um **objeto**/**classe** como um iterador nós precisamos implementar os métodos `__iter__()` e `__next__()` no nosso objeto. Como aprendemos no nosso capítulo de Classes e Objetos, todas as classes possuem uma função chamada `__init__()`, que possibilita a inicialização quando o objeto é criado. O método `__iter__()` age similar, pode executar operações (inicializações, etc), mas sempre deve retornar o objeto iterador. O método `__next__()` também possibilita operações e deve retornar o próximo item na sequência. 72 | 73 | ```python 74 | class Numeros: 75 | def __iter__(self): 76 | self.x = 1 77 | return self 78 | 79 | def __next__(self): 80 | y = self.x 81 | self.x += 1 82 | return y 83 | 84 | n = Numeros() 85 | iterador = iter(n) 86 | 87 | print(next(iterador)) 88 | print(next(iterador)) 89 | print(next(iterador)) 90 | print(next(iterador)) 91 | print(next(iterador)) 92 | # 1 93 | # 2 94 | # 3 95 | # 4 96 | # 5 97 | ``` 98 | 99 | ## StopIteration 100 | 101 | O exemplo acima pode ser executado infinitamente, especialmente se aplicarmos um **for loop**. Para previnirmos que a iteração ocorra eternamente, podemos usar o comando **StopIteration** no método `__next__()`, nós podemos adicionar a condição de término para que o erro seja disparado caso a iteração ultrapasse a condição. 102 | 103 | ```python 104 | class Numeros: 105 | def __iter__(self): 106 | self.x = 1 107 | return self 108 | 109 | def __next__(self): 110 | if self.x <= 6: 111 | y = self.x 112 | self.x +=1 113 | return y 114 | else: 115 | raise StopIteration 116 | 117 | n = Numeros() 118 | iterador = iter(n) 119 | 120 | for elemento in iterador: 121 | print(elemento) 122 | # 1 123 | # 2 124 | # 3 125 | # 4 126 | # 5 127 | # 6 128 | ``` 129 | 130 | ## Iterador Aleatório 131 | 132 | Vejamos um iterador que nos retorna sequências de comprimento aleatórios de **1**'s. 133 | 134 | ```python 135 | import random 136 | 137 | class RandomIterable: 138 | def __iter__(self): 139 | return self 140 | def __next__(self): 141 | if random.choice(["go", "go", "stop"]) == "stop": 142 | raise StopIteration # finaliza o iterador 143 | return 1 144 | 145 | for x in RandomIterable(): 146 | print(x) 147 | # 1 148 | # 1 149 | # 1 150 | ``` 151 | 152 | Esses foram os iteradores, conceito importante e muito presente em nossos estudos, central na linguagem Python, vamos então continuar **iterando** nosso conhecimento. 153 | -------------------------------------------------------------------------------- /content/for-loops.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'For Loops' 3 | description: 'Aprenda sobre For Loops' 4 | --- 5 | 6 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/ForLoop.png) 7 | 8 | O **For Loop** em Python é usado para iterar sob uma sequência (lista, tupla, string) ou outros objetos iteráveis. A iteração sob uma sequência também é conhecida como travessia. 9 | 10 | O **For Loop** já é um conhecido nosso, pois utilizamos ele para percorrer nossas listas no passado, porém agora veremos ele com uma maior riqueza de detalhes e veremos que ele é muito importante, uma vez que nos permite percorrer diversas sequências (**listas**, **tuplas**, **dicionários**, **sets** e até mesmo **strings**). 11 | 12 | Para escrevermos o **for** Loop devemos obedecer a seguinte sintaxe: 13 | 14 | ``` 15 | for seq in sequencia: 16 | print(seq) 17 | ``` 18 | 19 | Onde `seq` é a variável que recebe o valor do item dentro da sequência em cada iteração, o loop continua até alcançarmos o último item da sequência. 20 | 21 | É válido lembrar que o **for** em **Python** difere um pouco de outras linguagens como por exemplo **C**, onde nós podemos definir os passos de **iteração** e o momento de parada, em **Python** o **for** faz a iteração em cima dos itens de uma sequência, na ordem que eles aparecem naquela sequência, por exemplo: 22 | 23 | ```python 24 | animais = ["cachorro", "gato", "elefante"] 25 | 26 | for animal in animais: 27 | print(animal) 28 | ``` 29 | 30 | Simples, não? Também podemos percorrer **strings**: 31 | 32 | ```python 33 | for string in "Programação com Python": 34 | print(string) 35 | ``` 36 | 37 | Se quisermos evitar a quebra de linha `\n`, podemos alterar o valor do argumento **end**: 38 | 39 | ```python 40 | for string in "Programação com Python": 41 | print(string,end='') 42 | ``` 43 | 44 | ### A Função **range()** 45 | 46 | Nós podemos gerar sequências de números através da função **range()**. Por exemplo, **range(10)** irá gerar números de 0 até 9 (10 números). A função **range()** também nos permite definir o começo da nossa sequência, o fim e os passos que serão dados como por exemplo range(começo,fim,passos), caso não venhamos a definir os passos, o padrão é que seja de 1 em 1. 47 | 48 | Importante lembrar que a função não guarda todos os valores em memória por questões de eficiência, para forçarmos que a função imprima os itens, nós podemos utilizar a função **list()**, veja: 49 | 50 | ```python 51 | x = range(0,10) 52 | print(type(x)) # veja que o tipo retornado é 'range' 53 | print(list(x)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 54 | 55 | y = range(4,30,2) 56 | print(list(y)) # [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28] 57 | ``` 58 | 59 | Podemos aplicar a função **range()** em conjunto com o **for**: 60 | 61 | ```python 62 | for i in range(10): 63 | print(i) 64 | 65 | for data in range(1995,2018): 66 | print(data) 67 | ``` 68 | 69 | ### Condicionais 70 | 71 | A palavra-chave **break** nos permite parar o loop antes que ele passe por todos os itens 72 | 73 | ```python 74 | paises = ['China', 'Índia', 'Tailândia'] 75 | 76 | for pais in paises: 77 | print(pais) 78 | if pais == "Índia": 79 | break 80 | ``` 81 | 82 | Como podemos ver só serão impressos os países **China** e **Índia**, quando **pais** tiver o valor de **Índia** o loop irá parar e não será capaz de imprimir **Tailândia**. 83 | 84 | A palavra-chave **continue** nos permite parar a iteração atual do loop e continuar para a próxima: 85 | 86 | ```python 87 | linguagens = ['C','Javascript','Python','Lua'] 88 | 89 | for linguagem in linguagens: 90 | if linguagem == "Javascript": 91 | continue 92 | print(linguagem) 93 | ``` 94 | 95 | Como podem ver, ao chegamos em **Javascript** o loop pára e vai para a próxima impressão, nos retornando apenas 'C', 'Python' e 'Lua'. 96 | 97 | Dessa forma é muito fácil criarmos um **for loop** para imprimir apenas números pares: 98 | 99 | ```python 100 | for x in range(10): 101 | if x % 2 == 1: 102 | continue 103 | print(x) 104 | ``` 105 | 106 | Nos serão trazidos todos os números pares de 0 até 9. 107 | 108 | **Python** nos permite também usarmos a palavra-chave **else** em conjunto com o **for**, por exemplo: 109 | 110 | ```python 111 | for x in range(10): 112 | print(x) 113 | else: 114 | print("Loop finalizado com sucesso!") 115 | ``` 116 | 117 | ### Loops Encadeados 118 | 119 | Loops encadeados são loops dentro de loops, o "loop de dentro" será executado uma vez para cada iteração do "loop de fora". 120 | 121 | ```python 122 | cores = ['azul','verde','amarelo'] 123 | numeros = [1,2,3] 124 | 125 | for cor in cores: 126 | for numero in numeros: 127 | print(f'{cor.capitalize()} - {numero}') 128 | ``` 129 | 130 | ### Enumerando Valores 131 | 132 | O método **enumerate()** adiciona um contador a um iterável e o retorna o objeto enumerate. 133 | 134 | O método **enumerate()** recebe dois parâmetros: 135 | 136 | - **iterable**: Uma sequência, um iterator, ou objetos que suportam iteração 137 | - **start** (opcional): É o número que o método **enumerate()** iniciará contando, se **start** for omitido, 0 será o valor padrão. 138 | 139 | Vejamos um exemplo de como podemos usá-lo: 140 | 141 | ```python 142 | alimentos = ['arroz','feijão','batata'] 143 | 144 | for indice,alimento in enumerate(alimentos): 145 | print(f'{indice} -> {alimento}') 146 | ``` 147 | 148 | Informando o parâmetro start: 149 | 150 | ```python 151 | for indice,alimento in enumerate(alimentos,10): 152 | print(f'{indice} -> {alimento}') 153 | ``` 154 | 155 | Dessa vez ele começará a contar a partir do número **10**. 156 | 157 | Vimos nestes exemplos que as utilidades do **for** são imensas e podem nos ajudar bastante no sentido de percorrer sequências e até mesmo gerá-las com **range()**. 158 | -------------------------------------------------------------------------------- /content/geradores.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Geradores' 3 | description: 'Aprenda sobre Geradores' 4 | --- 5 | 6 | Introduzidos no [PEP 255](https://www.python.org/dev/peps/pep-0255), as funções geradoras são um tipo especial de função que retorna um [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation). Esses são objetos que você pode percorrer como uma lista. No entanto, ao contrário das listas, os lazy iterators não armazenam seu conteúdo na memória. 7 | 8 | Em outras palavras, **Geradores** são **iteradores**, porém só podemos iterar sob eles uma vez, pelo fato deles não guardarem todos os valores em memória, eles vão gerando os valores conforme instruímos. Nós usamos os geradores iterando sob eles, seja com um **for loop** ou passando eles para uma função ou constructo que seja capaz de iterar. 9 | 10 | Na maioria das vezes os geradores são implementados como **funções**, entretanto, eles não retornam um valor com **return**, eles usam a palavra chave **yield**, que seria uma forma de ir guardando os valores. 11 | 12 | Veja agora um exemplo de uma função geradora. 13 | 14 | ```python 15 | def gerador(): 16 | for e in range(5): 17 | yield e 18 | 19 | for item in gerador(): 20 | print(item) 21 | # 0 22 | # 1 23 | # 2 24 | # 3 25 | # 4 26 | ``` 27 | 28 | Veja que nesse caso não há muita utilidade, geradores são melhores para calcular **grandes quantidades** de resultados (particularmente cálculos que envolvem loops) onde não queremos alocar memória para todos os resultados ao mesmo tempo, trata-se de **eficiência**. 29 | 30 | Agora veja um gerador que é capaz de calcular números **fibonacci**: 31 | 32 | ```python 33 | def fib_gen(n): 34 | a = b = 1 35 | for e in range(n): 36 | a, b = b, a + b 37 | yield a 38 | 39 | for x in fib_gen(7): 40 | print(x) 41 | # 1 42 | # 1 43 | # 2 44 | # 3 45 | # 5 46 | # 8 47 | # 13 48 | ``` 49 | 50 | Também podemos definir um gerador que irá gerar uma **sequência infinita**: 51 | 52 | ```python 53 | def sequencia_infinita(): 54 | num = 0 55 | while True: 56 | yield num 57 | num +=1 58 | 59 | for i in sequencia_infinita(): 60 | print(i,end=' ') 61 | ``` 62 | 63 | Este programa irá executar infinitamente até que o paremos, podemos usar o comando `CTRL + C` para isso. Outra opção que temos é usar o método **next()**, dessa vez vamos controlar o número de iterações: 64 | 65 | ```python 66 | gen = sequencia_infinita() 67 | for _ in range(501): 68 | print(next(gen),end=',') 69 | ``` 70 | 71 | Dessa vez serão gerados números de 0 até 500. 72 | 73 | ## Expressões Geradoras 74 | 75 | **Python** nos permite criar simples geradores usando **expressões geradoras**, fazendo com que o processo de criação de geradores seja muito mais simples. Assim como as funções lambda criam funções anônimas, expressões geradoras criam funções geradoras anônimas. 76 | 77 | A sintaxe da expressão geradora nos lembra as **list comprehensions**, porém os colchetes são alterados para parênteses. A grande diferença entre os dois é que a compreensão de lista produz a lista inteira de uma só vez, enquanto que a expressão geradora produz um item de cada vez, fazendo dela muito mais eficiente em questões de desempenho e memória. 78 | 79 | Para o exemplo, vamos começar inicializando uma lista: 80 | 81 | ```python 82 | lista = [1, 3, 6, 10, 14] 83 | ``` 84 | 85 | Elevamos ao cubo cada elemento da lista, usando uma list comprehension: 86 | 87 | ```python 88 | [x**3 for x in lista] # [1, 27, 216, 1000, 2744] 89 | ``` 90 | 91 | Veja que de imediato obtemos uma nova lista com todos os elementos elevados ao cubo. Se quisermos alterar para uma expressão geradora, apenas precisamos trocar os colchetes por parênteses: 92 | 93 | ```python 94 | gerador = (x**3 for x in lista) 95 | print(gerador) # at 0x7fd0067de9d0> 96 | ``` 97 | 98 | Dessa vez nos é retornado um objeto generator, que podemos iterar sob ele: 99 | 100 | ```python 101 | for gen in gerador: 102 | print(gen) 103 | # 1 104 | # 27 105 | # 216 106 | # 1000 107 | # 2744 108 | ``` 109 | 110 | Observe que a **expressão geradora** não produziu o resultado que esperávamos de forma imediata, na verdade retornou um **objeto gerador**, que é capaz de produzir items sob demanda. 111 | 112 | Inicializamos agora uma outra lista para vermos como um gerador funciona ao usarmos o método **next()**: 113 | 114 | ```python 115 | l = [2,3,6,9] # 116 | 117 | a = (x**4 for x in l) 118 | 119 | print(next(a)) # 16 120 | print(next(a)) # 81 121 | print(next(a)) # 1296 122 | print(next(a)) # 6561 123 | print(next(a)) 124 | # Traceback (most recent call last): 125 | # File "", line 1, in 126 | # StopIteration 127 | ``` 128 | 129 | Veja que ao atingirmos o limite da lista, o erro **StopIteration** ocorre. 130 | 131 | As **expressões geradoras** também podem ser usadas dentro de funções, por exemplo: 132 | 133 | ```python 134 | numeros = [4,5,6,7] 135 | 136 | print(sum(x**4 for x in numeros)) # 4578 137 | print(max(x**4 for x in numeros)) # 2401 138 | ``` 139 | 140 | ## Importância dos Geradores 141 | 142 | Agora uma questão importante. Por que geradores são usados em Python? 143 | 144 | 1. Fácil de implementar, geradores podem ser implementados de maneira clara e concisa, de forma muito mais simples que os iteradores 145 | 2. Eficiência de memória, por produzirem um item por vez e não gerarem toda a sequência de uma só vez, os geradores nos trazem bastante perfomance. 146 | 3. Nos permitem produzir um fluxo infinito de dados, uma vez que esses fluxos não podem ser guardados em memória por serem infinitos, os geradores nos permitem trabalhar com eles, uma vez que itens serão gerados um por vez. 147 | 148 | Para entendermos a eficiência de memória de um gerador, vamos compará-lo com uma list comprehension para observarmos a diferença de tamanho entre eles. Vamos começar definindo uma função geradora: 149 | 150 | ```python 151 | def gen(n): 152 | for i in range(n): 153 | yield i**2 154 | ``` 155 | 156 | Agora vamos construir uma list comprehension com 100.000 elementos e um gerador com o mesmo número e usaremos a função **getsizeof** do módulo **sys** para obtermos a quantidade ocupada de memória do objeto em bytes: 157 | 158 | ```python 159 | import sys 160 | 161 | x = [i**2 for i in range(100_000)] 162 | g = gen(100_000) 163 | 164 | print(sys.getsizeof(x)) # 824472 165 | print(sys.getsizeof(g)) # 128 166 | ``` 167 | 168 | Veja que temos uma diferença substancial, com este exemplo, concluímos que os geradores são extremamente eficientes! 169 | -------------------------------------------------------------------------------- /content/ambiente.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Ambiente de Programação' 3 | description: 'Aprenda sobre Ambientes de Programação' 4 | --- 5 | 6 | Obter **Python** é muito fácil, para isso precisamos acessar o site oficial e fazer o download: **[python.org](https://www.python.org/downloads/)**. Recomendamos que você faça o download da versão mais recente e siga as *instruções de instalação*. Vale lembrar que se você usa o sistema operacional **MacOS** ou **Linux**, existem grandes chances do **Python** já estar instalado. 7 | 8 | Caso queira confirmar se **Python** está instalado no seu sistema, abra sua **[interface de linha de comando](https://pt.wikipedia.org/wiki/Interface_de_linha_de_comandos)** e digite: 9 | 10 | ``` 11 | python --version 12 | ``` 13 | 14 | Como você pôde observar, será retornada a versão atual do Python em sua máquina. 15 | 16 | ## Iniciando 17 | 18 | Antes de começarmos a programar, é de extrema importância que tenhamos um editor de texto eficiente e leve, para isso existem muitas opções excelentes: 19 | 20 | - [Sublime Text](https://www.sublimetext.com/) 21 | - [Brackets](http://brackets.io/) 22 | - [Notepad++](https://notepad-plus-plus.org/) 23 | - [Gedit](https://wiki.gnome.org/Apps/Gedit) 24 | - [Visual Studio Code](https://code.visualstudio.com/) 25 | - [Vim](https://www.vim.org/) 26 | - [Light Table](http://lighttable.com/) 27 | - [GNU Emacs](https://www.gnu.org/software/emacs/) 28 | 29 | Caso você tenha preferências por [Ambientes de Desenvolvimento Integrado](https://pt.wikipedia.org/wiki/Ambiente_de_desenvolvimento_integrado) mais robustos e completos, você pode optar por: 30 | 31 | - [Thonny](https://thonny.org/) 32 | - [PyCharm](https://www.jetbrains.com/pycharm/download/) 33 | - [IPython](https://ipython.org/) 34 | - [PyDev](http://www.pydev.org/) 35 | - [Spyder](https://www.spyder-ide.org/) 36 | 37 | Se eventualmente você desejar executar seus scripts Python em um ambiente online usando o seu Web Browser, você pode usar uma das seguintes opções: 38 | 39 | - [Python Shell](https://www.python.org/shell/) 40 | - [Repl.it](https://repl.it/languages/python3) 41 | - [Python Online Compiler](https://www.programiz.com/python-programming/online-compiler/) 42 | - [Python Tryit Editor](https://www.w3schools.com/python/trypython.asp?filename=demo_compiler) 43 | - [Online Python Interpreter](https://www.onlinegdb.com/online_python_interpreter) 44 | 45 | Nesse guia iremos utilizar o **Sublime Text**, porém sinta-se livre para escolher o editor que mais lhe agrada. Faça o download, siga os passos da instalação e vamos começar a nossa aventura! 46 | 47 | Assumindo que você está com o **Python** instalado em sua máquina e já tem um editor de texto em mãos, inicie o editor de Texto (a partir daqui assumiremos o Sublime Text como exemplo) e vá até `File -> New File`. Nesse arquivo vamos digitar nosso primeiro programa, o tradicional *Hello World*: 48 | 49 | ```python 50 | print("Hello World") # Hello World 51 | ``` 52 | 53 | Salve o arquivo, `File -> Save` ou através do atalho `CTRL + S`, importante você lembrar que a **[extensão dos arquivos](https://pt.wikipedia.org/wiki/Extensão_de_nome_de_ficheiro)** Python termina com `.py`, nesse caso nosso arquivo será chamado de **`hello.py`**, em seguida vá até `Tools -> Build System -> Python`. Agora que o Sublime Text está configurado para interpretar todos os nossos *scripts*, para executarmos ele devemos ir até `Tools -> Build` ou simplesmente através do atalho `CTRL + B`. 54 | 55 | Feito! Você acabou de escrever o seu primeiro programa em Python, se tudo ocorreu como esperado, aparecerá no console do **Sublime Text** a mensagem **Hello World**! 56 | 57 | ## Python Interativo 58 | 59 | Vale ressaltar também, como antes já citado, que o Python é capaz de rodar na **[interface de linha de comando](https://pt.wikipedia.org/wiki/Interface_de_linha_de_comandos)**, abra a sua e faça o teste digitando: 60 | 61 | ```python 62 | python3 63 | ``` 64 | 65 | Aparecerão algumas informações, como a versão do Python, sua data e você verá **`>>>`**, esse é o **interpretador** do Python, agora é só digitarmos: 66 | 67 | ```python 68 | >>> print("Hello World") # Hello World 69 | ``` 70 | 71 | Para obter ajuda no **interpretador** nós podemos utilizar a função **help()**, que recebe como parâmetro um **objeto** que desejamos entender melhor, por exemplo: 72 | 73 | ```python 74 | >>> help(float) # Nos trará informações sobre a classe float 75 | >>> help(print) # Nos trará informações sobre a função print 76 | ``` 77 | 78 | ## Filosofia Python 79 | 80 | Para conhecer a Essência & Filosofia da Linguagem Python você pode digitar o seguinte comando: 81 | 82 | ```python 83 | >>> import this 84 | ``` 85 | 86 | Nos será retornado: 87 | 88 | ``` 89 | The Zen of Python, by Tim Peters 90 | 91 | Beautiful is better than ugly. 92 | Explicit is better than implicit. 93 | Simple is better than complex. 94 | Complex is better than complicated. 95 | Flat is better than nested. 96 | Sparse is better than dense. 97 | Readability counts. 98 | Special cases aren't special enough to break the rules. 99 | Although practicality beats purity. 100 | Errors should never pass silently. 101 | Unless explicitly silenced. 102 | In the face of ambiguity, refuse the temptation to guess. 103 | There should be one-- and preferably only one --obvious way to do it. 104 | Although that way may not be obvious at first unless you're Dutch. 105 | Now is better than never. 106 | Although never is often better than *right* now. 107 | If the implementation is hard to explain, it's a bad idea. 108 | If the implementation is easy to explain, it may be a good idea. 109 | Namespaces are one honking great idea -- let's do more of those! 110 | ``` 111 | 112 | O **[Zen of Python](https://en.wikipedia.org/wiki/Zen_of_Python)**, escrito por Tim Peters descreve a filosofia e os princípios que guiam boas práticas da linguagem Python. 113 | 114 | Existe um *easter egg* muito divertido no Python, conhecido como *antigravity*, que nos redireciona para um quadrinho que ilustra o potencial da linguagem. Para vermos ele, devemos simplesmente importar o seguinte comando: 115 | 116 | ```python 117 | import antigravity 118 | ``` 119 | 120 | Nos será apresentado: 121 | 122 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/XkcdPython.png) 123 | 124 | Para sair do **interpretador** basta digitar o comando `exit()`, `quit()` ou `CTRL + D`. Agora que temos nosso ambiente de programação estabelecido, já estamos prontos para mergulhar em mares mais profundos e explorar as diversas capacidades que **Python** tem a nos oferecer, bem como todos os seus detalhes! 125 | -------------------------------------------------------------------------------- /content/sets.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Sets' 3 | description: 'Aprenda sobre Sets em Python' 4 | --- 5 | 6 | Sets são **coleções não-ordenadas** de itens **ÚNICOS**, embora um Set possa ser modificado, os elementos contidos dentro do Set devem ser imutáveis. Sets são definidos por valores separados por vírgula dentro de chaves `{}`. 7 | 8 | **Importante:** Cuidado para não confundir os Sets com os dicionários! 9 | 10 | A principal vantagem de usar um **Set**, ao contrário de uma lista, é que ele possui um mecanismo altamente otimizado para verificar se um elemento específico está contido nele. 11 | 12 | Talvez você lembre dos Sets através da **[famosa teoria matemática dos conjuntos](https://pt.wikipedia.org/wiki/Teoria_dos_conjuntos)**. 13 | 14 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Set.png) 15 | 16 | Os Sets podem ser usados para executarmos operações matemáticas de conjuntos como **união**, **intersecção**, **diferença simétrica**, etc. 17 | 18 | ### Definindo um Set 19 | 20 | Para definirmos um **Set** é muito simples: 21 | 22 | ```python 23 | s = {1,1,2,3,3,4} 24 | print(type(s)) # 25 | print(s) # {1, 2, 3, 4} 26 | ``` 27 | 28 | Observe que os valores repetidos foram eliminados de nosso set. 29 | 30 | Também podemos criar um set através do método **set()**: 31 | 32 | ```python 33 | k = set([1,2,3,4,5]) 34 | print(type(k)) # 35 | print(k) # {1, 2, 3, 4, 5} 36 | ``` 37 | 38 | Lembrando que podemos iterar sob um set com um **for loop**: 39 | 40 | ```python 41 | for itens in k: 42 | print(itens) 43 | ``` 44 | 45 | ### Operações com Sets 46 | 47 | O método **add()** nos possibilita adicionar um item ao set: 48 | 49 | ```python 50 | k.add(8) 51 | print(k) # {1, 2, 3, 4, 5, 8} 52 | ``` 53 | 54 | O método **discard()** nos permite remover itens de um set: 55 | 56 | ```python 57 | k.discard(1) 58 | print(k) # {2, 3, 4, 5, 8} 59 | ``` 60 | 61 | Para remover todos os elementos do set podemos usar o método **clear()**: 62 | 63 | ```python 64 | k.clear() 65 | print(k) # set() 66 | ``` 67 | 68 | Também podemos usar os sets para eliminar letras repetidas de uma palavra: 69 | 70 | ```python 71 | print(set('cachorro')) # {'o', 'a', 'c', 'r', 'h'} 72 | ``` 73 | 74 | Para sabermos o número de elementos em um set usamos o método **len()**: 75 | 76 | ```python 77 | len(set('cachorro')) # 5 78 | ``` 79 | 80 | Vamos agora definir dois novos sets `x` e `y` para testarmos **novas operações**. 81 | 82 | ```python 83 | x = {1,2,3} 84 | y = {2,3,4} 85 | ``` 86 | 87 | ### Intersecção 88 | 89 | Para intersecção podemos usar `&` ou o método **intersection()**. 90 | 91 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Intersec%C3%A7%C3%A3o.png) 92 | 93 | ```python 94 | print(x & y) # {2, 3} 95 | print(x.intersection(y)) # {2, 3} 96 | ``` 97 | 98 | ### Diferença 99 | 100 | Para diferença podemos usar `-` ou o método **difference()**. 101 | 102 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Diferen%C3%A7a.png) 103 | 104 | ```python 105 | # Relativo a x 106 | print(x - y) # {1} 107 | x.difference(y) # {1} 108 | 109 | # Relativo a y 110 | print(y - x) # {4} 111 | y.difference(x) # {4} 112 | ``` 113 | 114 | ### Diferença Simétrica 115 | 116 | Para diferença simétrica podemos usar `^` ou o método **symmetric_difference()**. 117 | 118 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Diferen%C3%A7aSim%C3%A9trica.png) 119 | 120 | ```python 121 | print(x.symmetric_difference(y)) # {1, 4} 122 | print(y.symmetric_difference(x)) # {1, 4} 123 | print(x ^ y) # {1, 4} 124 | print(y ^ x) # {1, 4} 125 | ``` 126 | 127 | Todos imprimem o mesmo resultado, uma vez que a diferença é simétrica. 128 | 129 | ### União 130 | 131 | Para união podemos usar `|` ou o método **union()**. 132 | 133 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Uni%C3%A3o.png) 134 | 135 | ```python 136 | print(x | y) # {1, 2, 3, 4} 137 | print(x.union(y)) # {1, 2, 3, 4} 138 | ``` 139 | 140 | ### Verificando a presença de um Elemento 141 | 142 | Assim como nas outras estruturas de dados compostas, nos sets também é possível verificarmos a **presença** ou **absência** de um determinado elemento com o uso da palavra-chave **in**, por sinal, os sets são muito eficientes para essas operações. 143 | 144 | ```python 145 | print(1 in x) # True 146 | print(5 in x) # False 147 | print(10 not in x) # True 148 | print(1 not in x) # False 149 | ``` 150 | 151 | ### Referência dos Sets 152 | 153 | Os Sets nos trazem diversas funcionalidades e nos permitem resolver diversos problemas, para conhecer mais detalhes sobre eles visite a **[documentação oficial](https://docs.python.org/3/tutorial/datastructures.html#sets)**. 154 | 155 | A tabela a seguir apresenta os métodos mais importantes dos sets e suas descrições: 156 | 157 | | Método | Descrição | 158 | |-------------------------------|:--------------------------------------------------------------------------------:| 159 | | add() | Adiciona um elemento ao set | 160 | | clear() | Remove todos os elementos do set | 161 | | copy() | Retorna uma cópia do set | 162 | | difference() | Retorna um set contendo a diferença entre dois ou mais sets | 163 | | difference_update() | Remove os itens desse set que também estão incluídos em outro set especificado | 164 | | discard() | Remove um item específico | 165 | | intersection() | Retorna um set que é intersecção entre dois sets | 166 | | intersection_update() | Remove os itens desse set que não estão presente em outro set especificado | 167 | | isdisjoint() | Retorna se dois sets possuem intersecção ou não | 168 | | issubset() | Retorna se outro set contém esse set ou não | 169 | | issuperset() | Retorna se esse set contém outro set ou não | 170 | | pop() | Remove o item especificado | 171 | | remove() | Remove o item especificado | 172 | | symmetric_difference() | Retorna um set com a diferença simétrica de dois sets | 173 | | symmetric_difference_update() | Insere a diferença simétrica desse set no outro | 174 | | union() | Retorna um set contendo a união de sets | 175 | | update() | Atualiza o set com a união desse set e outros | 176 | -------------------------------------------------------------------------------- /content/expressoes-lambda.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Expressões Lambda' 3 | description: 'Aprenda sobre Expressões Lambda' 4 | --- 5 | 6 | **Expressões lambda** também são conhecidas como **funções anônimas**, elas diferem das funções comuns por serem declaradas de maneira diferente, sem definirmos nome para criarmos elas, utilizamos a palavra-chave **lambda** para definí-las. 7 | 8 | Python e outras linguagens como Java, C# e até mesmo C++ tiveram as funções lambda adicionadas a sua sintaxe, já linguagens como LISP, ou linguagens da família **[ML](https://en.wikipedia.org/wiki/ML_(programming_language))**: Haskell, OCaml e F# usam lambdas como um conceito central. 9 | 10 | Expressões Lambda em Python e em outras linguagens de programação possuem suas raízes no **[cálculo lambda](https://en.wikipedia.org/wiki/Lambda_calculus)**, um modelo de computação inventando por **[Alonzo Church](https://en.wikipedia.org/wiki/Alonzo_Church)**. 11 | 12 | O cálculo lambda pode codificar qualquer cálculo, é [Turing completo](https://simple.wikipedia.org/wiki/Turing_complete), mas ao contrário do conceito de [máquina de Turing](https://en.wikipedia.org/wiki/Turing_machine), é puro e não guarda nenhum [estado](https://en.wikipedia.org/wiki/Turing_machine#The_%22state%22). 13 | 14 | As linguagens funcionais têm sua origem na lógica matemática e no cálculo lambda, enquanto as linguagens de programação imperativas adotam o modelo de computação baseado em estado inventado por Alan Turing. Os dois modelos de computação, cálculo lambda e máquinas de Turing, podem ser traduzidos um no outro. Essa equivalência é conhecida como [hipótese de Church-Turing](https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis). 15 | 16 | As linguagens funcionais herdam diretamente a filosofia do cálculo lambda, adotando uma abordagem declarativa de programação que enfatiza a abstração, a transformação de dados, a composição e a pureza (sem estado e sem efeitos colaterais). Exemplos de linguagens funcionais incluem Haskell e Lisp. 17 | 18 | - Expressões lambdas podem receber qualquer número de argumentos, porém retornam apenas um valor na forma de expressão, elas não podem ter comandos ou multiplas expressões 19 | - Uma função anônima não pode ser chamada diretamente pela função **print()**, pois ela requer uma expressão 20 | 21 | ### Funções Anônimas 22 | 23 | Os seguintes termos são usados de forma de forma intercambiável dependendo da linguagem de programação ou local que você vive: 24 | 25 | - Funções Anônimas 26 | - Funções Lambda 27 | - Expressões Lambda 28 | - Abstrações Lambda 29 | - Forma Lambda 30 | - Literais de Função 31 | 32 | ### Fundamentos Básicos 33 | 34 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Lambda.png) 35 | 36 | A estrutura para utilizarmos as funções lambdas é muito simples 37 | 38 | ``` 39 | lambda argumento1, argumento2, argumento3: expressão 40 | ``` 41 | 42 | Por exemplo, se quisermos multiplicar o argumento por **3**: 43 | 44 | ```python 45 | triplo = lambda x: x * 3 46 | print(type(triplo)) # 47 | print(triplo(3)) # 9 48 | ``` 49 | 50 | Se quisermos elevar o número ao quadrado: 51 | 52 | ```python 53 | quadrado = lambda x: x * x 54 | print(quadrado(5)) # 25 55 | ``` 56 | 57 | As expressões lambdas também nos permitem trabalharmos com strings, por exemplo: 58 | 59 | ```python 60 | nome_completo = lambda nome,sobrenome: f'Nome: {nome.title()}\nSobrenome: {sobrenome.title()}' 61 | print(nome_completo('isaac','newton')) 62 | # Nome: Isaac 63 | # Sobrenome: Newton 64 | ``` 65 | 66 | Podemos também usar **condicionais** com funções Lambda 67 | 68 | ```python 69 | comeca_com_G = lambda x: True if x.startswith('G') else False 70 | print(comeca_com_G('Gabriel')) # True 71 | print(comeca_com_G('Rafael')) # False 72 | ``` 73 | 74 | Se quisermos verificar se um determinado número é ímpar: 75 | 76 | ```python 77 | impar = lambda x: True if x % 2 == 1 else False 78 | print(impar(1)) # True 79 | print(impar(8)) # False 80 | ``` 81 | 82 | Até mesmo compor funções mais complexas, neste caso, imprimir a palavra que vem antes da palavra passada via argumento. 83 | 84 | ```python 85 | palavra_antes = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None 86 | sentenca = 'Rato Roeu Roupa Rei Roma' 87 | print(palavra_antes(sentenca,'Roma')) # Rei 88 | ``` 89 | 90 | ### Lambda em Python 91 | 92 | Nós normalmente usamos as funções Lambda quando precisamos de uma função por um período curto de tempo, podemos também usá-las como argumentos para funções de **high-order** (funções que recebem outras funções como argumento). 93 | 94 | **Funções lambda** também podem ser usadas com outras funções pré-construídas, como **filter()**, **map()**, etc. 95 | 96 | #### Filtrando 97 | 98 | Por exemplo, com **filter()**, que recebe uma função e uma lista como argumento. 99 | 100 | ```python 101 | lista = [1,2,3,4,5] 102 | 103 | nova_lista = list(filter(lambda x: (x % 2 == 0), lista)) 104 | 105 | print(nova_lista) # [2, 4] 106 | ``` 107 | 108 | Veja que a expressão lambda calculará o resto de divisão de cada valor da lista, caso o valor seja 0 o número será filtrado para nossa nova lista, formando assim uma lista de números pares. 109 | 110 | #### Mapeando 111 | 112 | Por exemplo, com **map()**, que também recebe uma função e uma lista como argumento. 113 | 114 | ```python 115 | lst = [3,5,6,7,9] 116 | 117 | nova_lst = list(map(lambda y: y * 10, lst)) 118 | 119 | print(nova_lst) # [30, 50, 60, 70, 90] 120 | ``` 121 | 122 | Dessa vez a expressão lambda multiplicará cada item da lista por 10 e estes serão mapeados em uma nova lista. 123 | 124 | Podemos usar esta ideia para converter de uma lista de temperaturas em grau Celsius para grau Fahrenheit. 125 | 126 | ```python 127 | celsius = [31.5, 22.1, 17.5, 42.8] 128 | 129 | fahrenheit = map(lambda x: (float(9)/5)*x + 32, celsius) 130 | 131 | print(list(fahrenheit)) # [88.7, 71.78, 63.5, 109.03999999999999] 132 | ``` 133 | 134 | #### Ordenando 135 | 136 | Através do método **sort()** podemos por exemplo organizar uma **lista** com uma expressão lambda. Vejamos um exemplo para ilustrar esta ideia: 137 | 138 | ```python 139 | alimentos = [('ovos', 10),('pães', 5),('tomate', 6),('cenoura', 4),('maçã', 3)] 140 | ``` 141 | 142 | Ordenando os alimentos por ordem alfabética: 143 | 144 | ```python 145 | alimentos.sort(key = lambda x: x[0]) 146 | print(alimentos) 147 | # [('cenoura', 4), ('maçã', 3), ('ovos', 10), ('pães', 5), ('tomate', 6)] 148 | ``` 149 | 150 | Ordenando os alimentos por quantidade crescente: 151 | 152 | ```python 153 | alimentos.sort(key = lambda x: x[1]) 154 | print(alimentos) 155 | # [('maçã', 3), ('cenoura', 4), ('pães', 5), ('tomate', 6), ('ovos', 10)] 156 | ``` 157 | 158 | Obtendo o alimento com a maior quantidade: 159 | 160 | ```python 161 | print(max(alimentos, key = lambda x: x[1])) # ('ovos', 10) 162 | ``` 163 | 164 | Obtendo o alimento com a menor quantidade: 165 | 166 | ```python 167 | print(min(alimentos, key = lambda x: x[1])) # ('maçã', 3) 168 | ``` 169 | 170 | #### Função que cria Funções 171 | 172 | É possível criarmos uma função que nos **retorna** uma expressão lambda para assim realizarmos cálculos: 173 | 174 | ```python 175 | # Função que cria funções 176 | def construcao_quadraticas(a, b, c): 177 | """Retorna a função f(x) = ax^2 + bx + c""" 178 | return lambda x: a*x**2 + b*x + c 179 | 180 | # Constrói uma nova função com os parâmetros (4,7,-6) 181 | f = construcao_quadraticas(4,7,-6) 182 | 183 | print(f(0)) # -6 184 | print(f(3)) # 51 185 | ``` 186 | 187 | Muito legal e útil, não? **Expressões lambdas** podem agilizar bastante nossa vida. 188 | -------------------------------------------------------------------------------- /content/numeros.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Números' 3 | description: 'Introdução aos números' 4 | --- 5 | 6 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Numbers.png) 7 | 8 | Em **Python** existem **três** tipos numéricos, são eles: 9 | 10 | - *int* 11 | - *float* 12 | - *complex* 13 | 14 | É importante lembrarmos que tudo em **Python** é um **objeto**, sendo assim, tipos de dados são **classes** e variáveis são instâncias (objetos) dessas classes, não se preocupe que veremos esses aspectos com mais detalhe ao longo do guia. 15 | 16 | Variáveis do tipo numérico são criadas quando atribuimos valores a elas: 17 | 18 | ```python 19 | a = 27 # int 20 | b = 22.2 # float 21 | c = 3j # complex 22 | ``` 23 | 24 | Para verificarmos qual classe a variável pertence, podemos utilizar a função **type()**: 25 | 26 | ```python 27 | print(type(a)) # 28 | print(type(b)) # 29 | print(type(c)) # 30 | ``` 31 | 32 | ## Int 33 | 34 | Inteiros são números **positivos**, **negativos**, que não apresentam casas decimais, seu tamanho é limitado apenas pela capacidade de memória disponível: 35 | 36 | ```python 37 | a = 3 38 | b = 342907249723902 39 | c = -100 40 | 41 | print(type(a)) # 42 | print(type(b)) # 43 | print(type(c)) # 44 | ``` 45 | 46 | ## Float 47 | 48 | Floats ou **"números de ponto flutuante"** são números positivos ou negativos que podem conter uma ou mais casas decimais: 49 | 50 | ```python 51 | a = 23.3 52 | b = 2.0 53 | c = -17.78 54 | 55 | print(type(a)) # 56 | print(type(b)) # 57 | print(type(c)) # 58 | ``` 59 | 60 | Podemos acrescentar o caracter **e** ou **E** seguido por um número inteiro positivo ou negativo para especificar a [notação científica](https://en.wikipedia.org/wiki/Scientific_notation). 61 | 62 | ```python 63 | e = 35e4 64 | print(type(e)) # 65 | print(e) # 350000.0 66 | 67 | E = 3.8e-2 68 | print(type(E)) # 69 | print(E) # 0.038 70 | ``` 71 | 72 | O valor máximo que um **float** pode ter é aproximadamente `1.8×10^308`. Qualquer número maior que este é indicado pelo valor **inf** (infinity). 73 | 74 | ```python 75 | print(1.79e308) # 1.79e+308 76 | print(1.8e308) # inf 77 | ``` 78 | 79 | Entretanto, o valor mínimo que um **float** pode ter é aproximadamente `5.0×10^-324`. Qualquer número menor que este é considerado **0** (zero). 80 | 81 | ```python 82 | print(5e-324) # 5e-324 83 | print(5e-325) # 0.0 84 | ``` 85 | 86 | ## Complex 87 | 88 | Números complexos são escritos com `j` representando a parte imaginária. Eles podem ser escritos `complex(3,4)` ou `3 + 4j`. Um número complexo Python `c` é armazenado internamente usando coordenadas Cartesianas ou Retangulares. 89 | 90 | Vejamos alguns exemplos: 91 | 92 | ```python 93 | a = 2+4j 94 | b = -3j 95 | c = complex(3,4) 96 | 97 | print(type(a)) # 98 | print(type(b)) # 99 | print(type(c)) # 100 | ``` 101 | 102 | Obtendo as partes **Real** e **Imaginária** de um número complexo: 103 | 104 | ```python 105 | print(c.real) # 3.0 106 | print(c.imag) # 4.0 107 | ``` 108 | 109 | ### Operações 110 | 111 | Realizando a operação de **adição** com números complexos: 112 | 113 | ```python 114 | x = complex(4,3) 115 | y = complex(-1,4) 116 | z = complex(2,1) 117 | 118 | print(x + y) # (3+7j) 119 | ``` 120 | 121 | Acrescentando um escalar adicionará à **parte real**: 122 | 123 | ```python 124 | print(x + 1) # (5+3j) 125 | ``` 126 | 127 | Também podemos realizar a operação de **multiplicação** com números complexos: 128 | 129 | ```python 130 | print(x * y) # (-16+13j) 131 | ``` 132 | 133 | Multiplicação por um Escalar: 134 | 135 | ```python 136 | print(x * 2) # (8+6j) 137 | ``` 138 | 139 | ### Extensão 140 | 141 | A função `abs(z)` retorna a extensão do número complexo `z`, em outras palavras, representa o cálculo da seguinte fórmula: 142 | 143 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/abs.png) 144 | 145 | ```python 146 | print(abs(z)) # 2.23606797749979 147 | ``` 148 | 149 | Também podemos realizar este cálculo com o auxílio da função **sqrt()** da biblioteca math. 150 | 151 | ```python 152 | from math import sqrt 153 | 154 | sqrt(z.real**2 + z.imag**2) # 2.23606797749979 155 | ``` 156 | 157 | ### Ângulo 158 | 159 | A função `phase()` retorna o ângulo `x` em radianos, porém, para usá-la teremos que importar a biblioteca **[cmath](https://docs.python.org/3/library/cmath.html)** em nosso código. 160 | 161 | Esta biblioteca nos traz funções matemáticas específicas para números complexos. 162 | 163 | ```python 164 | import cmath 165 | 166 | print(cmath.phase(x)) # 0.6435011087932844 167 | print(phase(complex(-1.0, 0.0))) # 3.1415926535897931 168 | print(phase(complex(-1.0, -0.0))) # -3.1415926535897931 169 | ``` 170 | 171 | O resultado estará entre [-π, π] 172 | 173 | ### Constante π and e 174 | 175 | A biblioteca cmath também nos traz constantes matemáticas como **e** e **pi**: 176 | 177 | ```python 178 | print(cmath.pi) # 3.141592653589793 179 | print(cmath.e) # 2.718281828459045 180 | ``` 181 | 182 | ## Números Aleatórios 183 | 184 | Embora Python não tenha uma função **random()** para nos gerar um número aleatório, existe um módulo construído em Python chamado `random` que nos permite criar números aleatórios: 185 | 186 | ```python 187 | import random 188 | 189 | print(random.randrange(1,10)) 190 | ``` 191 | 192 | A função acima gera números entre 1 e 9. 193 | 194 | Caso queira saber mais detalhes sobre o módulo `random` você pode visitar sua **[Referência](https://www.w3schools.com/python/module_random.asp)**. 195 | 196 | ## Conversão de Números 197 | 198 | A linguagem Python nos permite converter entre tipos numéricos. 199 | 200 | ```python 201 | k = 3 202 | i = 7.7 203 | z = 4j 204 | 205 | print(type(k)) # 206 | print(type(i)) # 207 | print(type(z)) # 208 | ``` 209 | 210 | Convertendo de **int** para **float**: 211 | 212 | ```python 213 | print(float(k)) # 3.0 214 | ``` 215 | 216 | Convertendo de **float** para **int**: 217 | 218 | ```python 219 | print(int(i)) # 7 220 | ``` 221 | 222 | Convertendo de **int** para **complex**: 223 | 224 | ```python 225 | print(complex(k)) # (3+0j) 226 | ``` 227 | 228 | Importante lembrar que não podemos converter um número complexo para outro tipo numérico. 229 | 230 | ## Bases 231 | 232 | Normalmente escrevemos inteiros na base 10. No entanto, Python nos permite escrever inteiros nos formatos **Hexadecimal** (base 16), **Octal** (base 8) e **Binário** (base 2). 233 | 234 | Podemos fazer isso adicionando um dos seguintes prefixos ao número inteiro: 235 | 236 | | Prefixo | Interpretação | Base | 237 | |---|---|--- | 238 | | `0b` ou `0B` | Binário | 2 | 239 | | `0o` ou `0O` | Octal | 8 | 240 | | `0x` or `0X` | Hexadecimal | 16 | 241 | 242 | Para esclarecer o funcionamento, vejamos alguns exemplos: 243 | 244 | ```python 245 | print(0b01111111) # 127 246 | print(0o10) # 8 247 | print(0XFF) # 255 248 | ``` 249 | 250 | O método **bin()** converte e retorna a string binária equivalente de um determinado inteiro. 251 | 252 | ```python 253 | bin(255) # '0b11111111' 254 | ``` 255 | 256 | Se quisermos convertê-lo de volta para o valor inteiro, podemos usar a função **int()**, passando a base 2 como argumento: 257 | 258 | ```python 259 | int('0b11111111',2) # 255 260 | ``` 261 | 262 | O método **oct()** converte e retorna a string octal equivalente de um determinado inteiro. 263 | 264 | ```python 265 | oct(8) # '0o10' 266 | ``` 267 | 268 | Se quisermos convertê-lo de volta para o valor inteiro, podemos usar a função **int()**, passando a base 8 como argumento: 269 | 270 | ```python 271 | int('0o10',8) # 8 272 | ``` 273 | 274 | O método **hex()** converte e retorna a string hexadecimal equivalente de um determinado inteiro. 275 | 276 | ```python 277 | hex(255) # '0xff' 278 | ``` 279 | 280 | Se quisermos convertê-lo de volta para o valor inteiro, podemos usar a função **int()**, passando a base 16 como argumento: 281 | 282 | ```python 283 | int('0xff',16) # 255 284 | ``` 285 | 286 | Lembre sempre que números são elementos essenciais e fundamentais na programação e que vamos utilizar muito eles! 287 | 288 | -------------------------------------------------------------------------------- /content/if-else.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'If... Else' 3 | description: 'Aprenda sobre Tomada de Decisão' 4 | --- 5 | 6 | A tomada de decisão é necessária quando queremos executar um código apenas se uma determinada **condição** for satisfeita. 7 | 8 | As instruções `if`, `elif` e `else` são usadas em Python para nos auxiliar na tomada de decisões. 9 | 10 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Conditionals.png) 11 | 12 | A tomada de decisão é um conceito muito importante da programação e representa a capacidade de executarmos determinados comandos apenas se condições especificadas forem satisfeitas. 13 | 14 | Lembrando que Python é capaz de suportar as condições lógicas tradicionais da matemática: 15 | 16 | - Igualdade: `x == y` 17 | - Diferente de: `x != y` 18 | - Menor que: `x < y` 19 | - Menor que ou igual a: `x <= y` 20 | - Maior que: `x > y` 21 | - Maior que ou igual a: `x >= y` 22 | 23 | Essas condições podem ser usadas de várias maneiras, e são comumente utilizadas em instruções **if** e **loops**. 24 | 25 | A sintaxe para construirmos uma estrutura de tomada de decisão funciona então da seguinte forma: 26 | 27 | ```pyhton 28 | if : 29 | 30 | elif : 31 | 32 | else: 33 | 34 | ``` 35 | 36 | Neste exemplo, o programa executa a primeira linha `if `, se a `` for avaliada como `True`, os `` dentro do bloco **if** serão executados. 37 | 38 | Caso a `` da primeira linha `if ` seja avaliada como `False`, nosso programa irá pular para a linha `elif ` e irá testar a nova ``: 39 | 40 | - Se ela for avaliada como `True` os comandos do bloco **elif** serão executados. 41 | - Se ela for avaliada como `False` os comandos do bloco **else** serão executados. 42 | 43 | ### Exemplos 44 | 45 | Vamos agora construir exemplos práticos para compreender melhor a ideia de tomada de decisão em nossos códigos. 46 | 47 | ```python 48 | num = 5 49 | 50 | if num > 0: 51 | print("O número é positivo") 52 | print("Esse valor é sempre impresso, pois está fora do bloco if") 53 | ``` 54 | 55 | Nesse caso podemos perceber que a expressão dentro do bloco **if** será executa, uma vez que o valor de **num** é maior que **0**, sendo assim, **positivo**. 56 | 57 | Também podemos usar a palavra-chave **elif** para testarmos outras possibilidades, uma vez que nem sempre a primeira pode ser atendida. 58 | 59 | ```python 60 | x = 12 61 | y = 12 62 | 63 | if x > y: 64 | print("x é maior do que y") 65 | elif x == y: 66 | print("x e y são iguais") 67 | ``` 68 | 69 | Nesse exemplo a primeira condição não é satisfeita, então pulamos para o **elif** e fazemos o teste, como os valores de **x** e **y** são iguais, temos nossa expressão **"x e y são iguais"** executada. 70 | 71 | Além do **if** e **elif**, temos o **else** que preencherá qualquer situação que o **if** e **elif** não sejam capazes de executar. 72 | 73 | ```python 74 | a = 100 75 | b = 20 76 | 77 | if b > a: 78 | print("b é maior do que a") 79 | elif b == a: 80 | print("b e a são iguais") 81 | else: 82 | print("a é maior do que b") 83 | ``` 84 | 85 | Veja que nesse caso o primeiro **if** será avaliado como **False**, pulamos então para o **elif** que também será avaliado como **False**, nos deixando apenas com a execução do **else**. 86 | 87 | Lembrando que é possível utilizarmos o **else** sem o **elif**. 88 | 89 | ```python 90 | k = 30 91 | z = 22 92 | 93 | if z > k: 94 | print("z é maior do que k") 95 | else: 96 | print("k é maior do que z") 97 | ``` 98 | 99 | Podemos também encadear multiplos **if**, **elif** e **else**. 100 | 101 | Nesse programa vamos pedir para o usuário entrar com um número, avaliaremos se ele é positivo, negativo ou zero e mostraremos ao usuário a mensagem apropriada. 102 | 103 | ```python 104 | num = int(input("Digite um número: ")) 105 | 106 | if num >= 0: 107 | if num == 0: 108 | print("Zero") 109 | else: 110 | print("Número positivo") 111 | else: 112 | print("Número negativo") 113 | ``` 114 | 115 | Imagine agora que temos uma string chamada de **senha** e queremos avaliar se ela foi digitada ou não, podemos neste caso usar a palavra-chave **not** que indica a negação de uma expressão, alterando assim seu estado. Por exemplo: 116 | 117 | ```python 118 | senha = '' 119 | 120 | if not senha: 121 | print('Senha inexistente!') 122 | else: 123 | print('Senha existe!') 124 | # Senha inexistente! 125 | ``` 126 | 127 | Neste caso específico, o comando `print('Senha inexistente!')` será executado, uma vez que qualquer string vazia é avaliada como `False`, e nesse caso, usamos o **not** para trocar o **False** para **True**. 128 | 129 | Podemos confirmar essa ideia com o seguinte experimento: 130 | 131 | ```python 132 | print(bool('')) # False 133 | print(bool('75966231325')) # True 134 | ``` 135 | 136 | Isso quer dizer que se adicionarmos uma senha, o bloco **else** será executado, pois dessa vez temos uma string preenchida, que será avalida como **True** e a palavra-chave **not** irá transformar o **True** em **False**. 137 | 138 | ```python 139 | senha = '75966231325' 140 | 141 | if not senha: 142 | print('Senha inexistente!') 143 | else: 144 | print('Senha existe!') 145 | # Senha existe! 146 | ``` 147 | 148 | No caso de números, o que ocorre é que o número **0** é avaliado como `False` e quaisquer outros números são considerados `True`: 149 | 150 | ```python 151 | bool(0) # False 152 | bool(1) # True 153 | bool(-1) # True 154 | bool(3.3) # True 155 | bool(3+1j) # True 156 | ``` 157 | 158 | ### Operadores Lógicos 159 | 160 | Anteriormente vimos os **operadores lógicos**, eles também podem ser utilizados em conjunto com **if** para construirmos testes mais elaborados. 161 | 162 | A palavra-chave **and** é um operador lógico e é usado para combinar declarações condicionais: 163 | 164 | ```python 165 | n1 = 15 166 | n2 = 30 167 | n3 = 15 168 | 169 | if n1 < n2 and n3 == n1: 170 | print("Ambas as condições são verdadeiras") 171 | ``` 172 | 173 | Neste exemplo o comando **print()** será executado, pois ambas as condições se concretizam como `True` (n1 é **menor** que n2 e n3 é **igual** a n1). 174 | 175 | A palavra-chave **or** é um operador lógico e é usada para combinar declarações condicionais: 176 | 177 | ```python 178 | 179 | 180 | if n1 > n2 or n1 == n3: 181 | print("Pelo menos uma condição é verdadeira") 182 | ``` 183 | 184 | Neste exemplo o comando **print()** será executado, mesmo a primeira expressão não sendo avaliada como `True`, a segunda é avaliada, o que é o suficiente para termos nosso comando **print()** executado. 185 | 186 | ### O Desafio FizzBuzz 187 | 188 | Imagine que temos um número **n**. Temos que exibir uma representação em string de todos os números de **1** até **n**, mas existem algumas restrições: 189 | 190 | - Se o número n for divisível por 3, imprimir "Fizz" ao invés do número. 191 | - Se o número n for divisível por 5, imprimir "Buzz" ao invés do número. 192 | - Se o número n for divisível por 3 e 5, imprimir "FizzBuzz" ao invés do número 193 | 194 | Em outras palavras, para múltiplos de três vamos imprimir "Fizz" em vez do número e para múltiplos de cinco vamos imprimir "Buzz". Para números que são múltiplos de três e cinco, imprimir "FizzBuzz". 195 | 196 | Para resolvermos este problema, precisaremos de um **for loop** e uma série de testes com **if**, **elif** e **else**. Vejamos como podemos fazer: 197 | 198 | ```python 199 | n = 35 200 | 201 | for n in range(1,n): 202 | if n % 3 is 0 and n % 5 is 0: 203 | print("FizzBuzz") 204 | elif n % 3 is 0: 205 | print("Fizz") 206 | elif n % 5 is 0: 207 | print("Buzz") 208 | else: 209 | print(n) 210 | ``` 211 | 212 | Observe que estamos usando o operador de resto de divisão (`%`) e também a palavra-chave **is**, para verificarmos se o resto de divisão é igual a 0. 213 | 214 | - No primeiro bloco **if** testamos se o número é divisível por 3 e 5. 215 | - No segundo bloco **elif** testamos se o número é divisível por 3. 216 | - No terceiro bloco **elif** testamos se o número é divisível por 5. 217 | - Finalmente, se todas os testes anteriores forem `False`, iremos imprimir o próprio número **n**. 218 | 219 | É importante fixarmos bastante a parte de **tomada de decisão**, pois ela nos dará uma base sólida para construirmos nossos programas, lembre sempre de fazer experimentos. 220 | -------------------------------------------------------------------------------- /content/tipos-variaveis.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Tipos de Variáveis' 3 | description: 'Aprenda sobre os Tipos de Variáveis em Python' 4 | --- 5 | 6 | **Variáveis** são um conceito de extrema importância nas linguagens de programação. 7 | 8 | Variáveis são usadas para armazenar informações a serem referenciadas e manipuladas em um programa de computador. Elas também fornecem uma maneira de rotular dados com um nome descritivo, para que nossos programas possam ser entendidos mais claramente pelo leitor e por nós mesmos. É útil pensar nas variáveis como contêineres que contêm informações. Seu único objetivo é rotular e armazenar dados na memória. Esses dados podem ser usados em todo o seu programa. 9 | 10 | ## Atribuindo Valores às Variáveis 11 | 12 | As variáveis em **Python** não precisam declaração explícita para reservar espaço em memória, a declaração ocorre automaticamente quando você atribui um valor à variável. O sinal de **(=)** é usado para fazer a atribuição de valores. 13 | 14 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Variables.png) 15 | 16 | Por exemplo: 17 | 18 | ```python 19 | nome = 'Gabriel' # Uma string 20 | idade = 33 # Um valor inteiro 21 | altura = 1.75 # Um valor em ponto flutuante 22 | 23 | print(nome) # Gabriel 24 | print(idade) # 33 25 | print(altura) # 1.71 26 | ``` 27 | 28 | Também é possível atribuir múltiplos valores para múltiplas variáveis: 29 | 30 | ```python 31 | a, b, c = 5, 3.1, "Hello" 32 | 33 | print(a) # 5 34 | print(b) # 3.1 35 | print(c) # Hello 36 | ``` 37 | 38 | Um detalhe importante que não podemos esquecer é que devemos dar nomes que façam sentido as nossas variáveis, existem também notações que são usadas por programadores, por exemplo **camelCase**, onde a variável começa com uma letra em lowercase, por exemplo: 39 | 40 | ```python 41 | meuNome = "Gabriel" 42 | minhaIdade = 33 43 | meuEndereco = "Avenida Castelo" 44 | ``` 45 | 46 | Letras capitalizadas podem ser usadas para declarar **constantes**, valores que não variam, exemplo: 47 | 48 | ```python 49 | PI = 3.14 50 | GRAVIDADE = 9.8 51 | ``` 52 | 53 | ## Tipos de Variáveis em Python 54 | 55 | Em muitas linguagens de programação, as variáveis são [statically typed](https://en.wikipedia.org/wiki/Type_system#Static_type_checking). Isso significa que uma variável é inicialmente declarada como tendo um tipo de dados específico e qualquer valor atribuído a ela durante sua vida útil deve sempre ter esse tipo. 56 | 57 | Variáveis em Python não estão sujeitas a esta restrição. No Python, uma variável pode ser atribuída a um valor de um tipo e, posteriormente, re-atribuída a um valor de um tipo diferente: 58 | 59 | ```python 60 | v = 100 61 | print(v) # 100 62 | 63 | v = 'agora sou uma string' 64 | print(v) # agora sou uma string 65 | ``` 66 | 67 | ## Referências a Objetos 68 | 69 | Python é uma linguagem [orientada a objetos](https://en.wikipedia.org/wiki/Object-oriented_programming). De fato, praticamente todos os itens de dados em um programa Python são objetos de um tipo ou classe específica. 70 | 71 | Consideramos agora o seguinte código 72 | 73 | ```python 74 | print(33) 75 | ``` 76 | 77 | Ao apresentarmos o interpretador o seguinte [statement](https://en.wikipedia.org/wiki/Statement_(computer_science)) `print(33)`, ele executará as seguintes ações: 78 | 79 | - Criará um objeto inteiro 80 | - Dará a ele o valor 33 81 | - Apresentará ele no console 82 | 83 | Podemos usar a função construída **type()** para confirmarmos 84 | 85 | ```python 86 | type(33) # 87 | ``` 88 | 89 | Uma variável Python é um nome simbólico que é uma referência ou ponteiro para um objeto. Uma vez que um objeto é atribuído a uma variável, você pode se referir ao objeto com esse nome. Mas os dados em si ainda estão contidos no objeto. 90 | 91 | Consideramos o seguinte exemplo: 92 | 93 | ```python 94 | x = 33 95 | ``` 96 | 97 | Esta atribuição cria um **objeto integer** com o valor `33` e atribui a variável `x` para apontar para este objeto 98 | 99 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/x.png) 100 | 101 | Agora vamos considerar o seguinte statement 102 | 103 | ```python 104 | y = x 105 | ``` 106 | 107 | Ao executarmos ele, Python não criará outro objeto, ele simplesmente criará um nome simbólico ou referência `y`, no qual aponta para o mesmo objeto que aponta para `x`. 108 | 109 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/xy.png) 110 | 111 | Imagine agora que façamos essa alteração 112 | 113 | ```python 114 | y = 13 115 | ``` 116 | 117 | Dessa vez, Python criará um novo **objeto integer** com o valor `13`, e `y` se tornará uma referência para ele. 118 | 119 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/x-y.png) 120 | 121 | Agora imagine que venhamos a executar o seguinte statement 122 | 123 | ```python 124 | x = 'e' 125 | ``` 126 | 127 | Python criará um **objeto string** com o valor `'e'` e fará de `x` uma referência a ele. 128 | 129 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/x_y.png) 130 | 131 | Como podemos observar, não há mais referência ao objeto integer `33`. Quando o número de referências a um objeto cai para zero, ele não está mais acessível. Nesse ponto, sua vida acabou. O Python eventualmente perceberá que é inacessível e recuperará a memória alocada para que possa ser usada para outra coisa. Esse processo é chamado de [garbage collection](https://stackify.com/python-garbage-collection/). 132 | 133 | ## Identidade dos Objetos 134 | 135 | No Python, todo objeto criado recebe um número que o identifica exclusivamente. É garantido que dois objetos não terão o mesmo identificador durante qualquer período em que sua vida útil se sobreponha. 136 | 137 | A função construída **id()** retorna o identificador inteiro de um objeto. Utilizando a função **id()** podemos verificar se duas variáveis realmente apontam para o mesmo objeto: 138 | 139 | ```python 140 | k = 100 141 | t = k 142 | id(k) # 94320283578208 143 | id(t) # 94320283578208 144 | ``` 145 | 146 | Perceba que ambas possuem o mesmo número identificador, uma vez que elas apontam para o mesmo objeto. Caso façamos uma alteração em `t`, ele passará a apontar para outro objeto, ganhando assim um **id** diferente. 147 | 148 | ```python 149 | t = 50 150 | id(t) # 94320283576608 151 | ``` 152 | 153 | ## Deletando uma Variável 154 | 155 | O comando **del** nos permite deletar variáveis. 156 | 157 | No exemplo abaixo, declaramos uma variável chamada de **numero** e atribuímos um valor ponto flutuante a ela, em seguida, utilizamos o comando **del** para deletá-la. 158 | 159 | ```python 160 | numero = 12.5 161 | del numero 162 | ``` 163 | 164 | Se eventualmente tentarmos imprimí-la no console com o comando `print()` nos será retornado um erro: `NameError: name 'numero' is not defined`, nos indicando que ela não está mais definida. 165 | 166 | ## Nomes de Variáveis 167 | 168 | Uma variável pode ter um nome curto (como por exemplo **x** ou **y**) e ou nome mais descritivo (**nome**, **idade**, **resultado**). 169 | 170 | Veja as regras para as variáveis 171 | 172 | - Uma variável deve iniciar com uma letra ou um caracter *underscore* (**_**) 173 | - Uma variável não pode começar com um número 174 | - O nome de uma variável pode conter apenas caracteres alpha-numéricos e *underscores* (A-z, 0-9, e _) 175 | - Nomes de variáveis são *case sensitive* (idade, Idade e IDADE são três variáveis diferentes) 176 | 177 | ## Variáveis Globais 178 | 179 | Em Python, uma variável declarada fora da função ou no escopo global é conhecida como variável global. Isso significa que uma variável global pode ser acessada dentro ou fora da função. 180 | 181 | Vejamos um exemplo de como uma variável global é criada em Python: 182 | 183 | ```python 184 | x = 'global' 185 | 186 | def imprimir(): 187 | print(f'{x} na função imprimir()') 188 | 189 | imprimir() 190 | print(f'{x} fora da função') 191 | ``` 192 | 193 | No código acima, criamos **x** como uma variável global e definimos `imprimir()` para imprimir a variável global x. Finalmente, chamamos o `imprimir()` que imprimirá o valor de x, além disso, usamos o comando `print()` que também irá imprimir x. 194 | 195 | E se desejarmos alterar o valor de x dentro de uma função? 196 | 197 | ```python 198 | x = 3 199 | 200 | def add(): 201 | x = x + 5 202 | print(x) 203 | 204 | add() 205 | ``` 206 | 207 | Nos será retornado o seguinte erro: 208 | 209 | ``` 210 | UnboundLocalError: local variable 'x' referenced before assignment 211 | ``` 212 | 213 | O *output* apresenta um erro porque o Python trata **x** como uma variável local e **x** também não está definido dentro da função `add()`. 214 | 215 | Para solucionar este problema, podemos criar uma variável global dentro de uma função, para isso usamos a palavra-chave **global**: 216 | 217 | ```python 218 | x = 3 219 | 220 | def add(): 221 | global x 222 | x = x + 5 223 | print(x) 224 | 225 | add() # 8 226 | ``` 227 | 228 | Observe que dessa vez a função tem acesso à variável x, tornando assim possível adicionarmos o número 5. 229 | 230 | Agora que você já consegue armazenar valores em variáveis, vamos ver os tipos de dados que existem em **Python** e suas aplicações! 231 | -------------------------------------------------------------------------------- /content/tuplas.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Tuplas' 3 | description: 'Aprenda sobre as Tuplas em Python' 4 | --- 5 | 6 | Tuplas são uma sequência de **objetos imutáveis**, em outras palavras, uma vez criadas, tuplas não podem ser modificadas, normalmente são usadas para guardar **dados protegidos**. 7 | 8 | As tuplas são escritas entre parênteses **()**. 9 | 10 | Uma tupla em Python é semelhante a uma lista. A diferença entre os dois é que não podemos alterar os elementos de uma tupla depois de atribuída, enquanto podemos alterar os elementos de uma lista. 11 | 12 | ### Criando uma Tupla 13 | 14 | Podemos definir uma tupla da seguinte maneira: 15 | 16 | ```python 17 | linguagens = ("Python","Ruby","Javascript","Perl","Haskell") 18 | print(linguagens) # ('Python', 'Ruby', 'Javascript', 'Perl', 'Haskell') 19 | ``` 20 | 21 | Com o método **type()** podemos confirmar que se trata de uma **'tuple'**: 22 | 23 | ```python 24 | type(linguagens) # 25 | ``` 26 | 27 | ### Acessando Itens de uma Tupla 28 | 29 | O acesso aos itens de uma tupla é idêntico ao de uma lista: 30 | 31 | ```python 32 | print(linguagens[0:2]) # ('Python', 'Ruby') 33 | print(linguagens[-1]) # Haskell 34 | print(linguagens[:-2]) # ('Python', 'Ruby', 'Javascript') 35 | print(linguagens[:]) # ('Python', 'Ruby', 'Javascript', 'Perl', 'Haskell') 36 | ``` 37 | 38 | ### Atualizando Tuplas 39 | 40 | Lembrando que as tuplas são imutáveis, portanto se tentarmos modificá-la, nos será retornado um erro do tipo **TypeError**: 41 | 42 | ```python 43 | linguagens[0] = "C++" 44 | # TypeError: 'tuple' object does not support item assignment 45 | ``` 46 | 47 | Como já mencionado, Tuplas são imutáveis, ou seja, não podemos alterar os seus elementos, porém podemos capturar porções de uma tupla e criar novas tuplas, por exemplo: 48 | 49 | ```python 50 | x = (1,2) 51 | y = (3,4) 52 | 53 | z = x + y 54 | print(z) # (1, 2, 3, 4) 55 | ``` 56 | 57 | ### Imprimindo Elementos de uma Tupla 58 | 59 | As tuplas são úteis para representar o que outras linguagens costumam chamar de registros, algumas informações relacionadas que pertencem entre si, como o registro de um **estudante**. Não há descrição do que significa cada um desses campos, mas podemos intuir. Uma tupla nos permite “agrupar” informações relacionadas e usá-las em uma única estrutura. 60 | 61 | ```python 62 | estudante = ('Miguel', 29, 1990, 'Brasil') 63 | ``` 64 | 65 | Agora podemos utilizar um **for loop** para imprimir todos os elementos da tupla **estudante**: 66 | 67 | ```python 68 | for e in estudante: # Percorre os valores da tupla estudante 69 | print(e) # Imprime os valores 70 | ``` 71 | 72 | Também podemos facilmente converter esta tupla em uma lista usando a técnica list comprehension: 73 | 74 | ```python 75 | print([e for e in estudante]) # ['Miguel', 29, 1990, 'Brasil'] 76 | ``` 77 | 78 | ### Checando por Valores em uma Tupla 79 | 80 | Assim como nas listas, também podemos checar se determinado item está presente em uma tupla: 81 | 82 | ```python 83 | print('Gabriel' in estudante) # False 84 | ``` 85 | 86 | ```python 87 | print(1990 in estudante) # True 88 | ``` 89 | 90 | Além disso, podemos checar também a absência de determinado elemento: 91 | 92 | ```python 93 | print('Japão' not in estudante) # True 94 | ``` 95 | 96 | ```python 97 | print('Brasil' not in estudante) # False 98 | ``` 99 | 100 | ### Verificando o Tamanho de uma Tupla 101 | 102 | Para obtermos o número de itens em uma tupla, podemos usar o método **len()**: 103 | 104 | ```python 105 | print(len(estudante)) # 4 106 | ``` 107 | 108 | ### Deletando a Tupla 109 | 110 | Embora seja impossível remover itens da tupla, é possível deletá-la por completo com o uso da palavra-chave **del**. Observe que se tentarmos imprimir ela, ocorrerá um erro do tipo **NameError**, uma vez que a tupla não existe mais. 111 | 112 | ```python 113 | del estudante 114 | print(estudante) 115 | # NameError: name 'estudante' is not defined 116 | ``` 117 | 118 | ### Construtor tuple() 119 | 120 | Somos capazes também de construir uma tupla com o uso do construtor **tuple()**: 121 | 122 | ```python 123 | numeros = tuple(x for x in range(1,20,3)) 124 | print(numeros) # (1, 4, 7, 10, 13, 16, 19) 125 | ``` 126 | 127 | ### Método count() 128 | 129 | O método **count()** nos retorna a quantidade de vezes que determinado valor ocorre em uma tupla 130 | 131 | ```python 132 | print(numeros.count(7)) # 1 133 | ``` 134 | 135 | ### Método index() 136 | 137 | O método **index()** nos permite buscar por um determinado elemento e nos retorna o índice dele: 138 | 139 | ```python 140 | numeros.index(4) # 1 141 | ``` 142 | 143 | ### Criando uma Função que Retorna uma Tupla 144 | 145 | Funções normalmente retornam apenas um **único valor**, porém ao tornarmos esse valor uma **Tupla**, nós podemos efetivamente agrupar a quantidade de valores que desejarmos e retorná-los juntos. Esta funcionalidade pode nos ser muito útil em casos que queiramos por exemplo encontrar a **média** e o **desvio padrão** ou talvez obter o ano, mês e dia. 146 | 147 | Vejamos um exemplo para ilustrar esta ideia, em que vamos definir uma função de nome **f** que irá calcular a **circunferência** e a **área** de um círculo de raio **r** (o raio será informado via argumento por nós): 148 | 149 | ```python 150 | import math 151 | 152 | def f(r): 153 | """ Retorna (circunferência, área) de um círculo de raio r """ 154 | c = 2 * math.pi * r 155 | a = math.pi * r * r 156 | return (c, a) 157 | 158 | print(f(5)) # (31.41592653589793, 78.53981633974483) 159 | print(f(8)) # (50.26548245743669, 201.06192982974676) 160 | ``` 161 | 162 | ### Named Tuples 163 | 164 | **Named Tuples** são objetos de fácil criação e leves. Instâncias de Named Tuples podem ser referenciadas utilizando variáveis. Elas podem serem utilizadas como uma espécie de estrutura para agruparmos dados. 165 | 166 | É muito comum representarmos um ponto como uma tupla (x, y). 167 | 168 | A fórmula da distância é uma expressão algébrica usada para determinar a distância entre dois pontos com as coordenadas (x1, y1) e (x2, y2). 169 | 170 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/DistanceFormula.png) 171 | 172 | ```python 173 | from math import sqrt 174 | 175 | p1 = (2.0, 7.0) 176 | p2 = (2.5, 3.5) 177 | 178 | comprimento_linha = sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2) 179 | print(comprimento_linha) # 3.5355339059327378 180 | ``` 181 | 182 | Ao utilizarmos uma Named Tuple, nosso código se torna mais legível, porém para usá-la devemos importá-la da biblioteca [collections](https://docs.python.org/3/library/collections.html): 183 | 184 | ```python 185 | from collections import namedtuple 186 | 187 | Ponto = namedtuple('Point', 'x y') 188 | p1 = Ponto(1.5, 5.0) 189 | p2 = Ponto(4.5, 1.5) 190 | 191 | comprimento_linha = sqrt((p1.x-p2.x)**2 + (p1.y-p2.y)**2) 192 | print(comprimento_linha) # 4.6097722286464435 193 | ``` 194 | 195 | Podemos usar as Named Tuples para armazenar cores **RGB**: 196 | 197 | ```python 198 | Cor = namedtuple('Cor', ['red', 'green', 'blue']) 199 | 200 | cor = Cor(55,155,255) 201 | 202 | print(cor) # Cor(red=55, green=155, blue=255) 203 | print(cor.red) # 55 204 | ``` 205 | 206 | ### Tuplas vs Listas 207 | 208 | Por que devemos usar uma Tupla ao invés de uma Lista? 209 | 210 | - A execução do programa é mais rápida quando manipulamos uma tupla do que uma equivalente lista. 211 | - As vezes desejamos que os dados não sejam modificados, se determinados que valores em uma coleção devem ser constantes no programa, utilizar uma Tupla nos protege contra acidentes de modificação. 212 | 213 | #### Exemplos 214 | 215 | Exemplo de Lista: 216 | 217 | ```python 218 | numeros_primos = [2, 3, 5, 7, 11, 13, 17] 219 | ``` 220 | 221 | Mostrando o tamanho: 222 | 223 | ```python 224 | print(f'# Primos: {len(numeros_primos)}') 225 | ``` 226 | 227 | Iterando sob a sequência: 228 | 229 | ```python 230 | for p in numeros_primos: 231 | print(f'Primos: {p}') 232 | ``` 233 | 234 | Exemplo de Tupla: 235 | 236 | ```python 237 | quadrados_perfeitos = (1, 4, 9, 16, 25, 36) 238 | ``` 239 | 240 | Mostrando o tamanho: 241 | 242 | ```python 243 | print(f'# Quadrados Perfeitos: {len(quadrados_perfeitos)}') 244 | ``` 245 | 246 | Iterando sob a sequência: 247 | 248 | ```python 249 | for n in quadrados_perfeitos: 250 | print(f'Primos: {n}') 251 | ``` 252 | 253 | #### Métodos das Listas e Tuplas 254 | 255 | Podemos usar o método **dir()** para visualizarmos todos os atributos e métodos disponíveis nas listas e tuplas: 256 | 257 | ```python 258 | print('Métodos Lista') 259 | print(dir(numeros_primos)) 260 | print('Métodos Tupla') 261 | print(dir(quadrados_perfeitos)) 262 | ``` 263 | 264 | #### Obtendo o Tamanho em Bytes 265 | 266 | O método **getsizeof()** da biblioteca [sys](https://docs.python.org/3/library/sys.html) nos permite obter o tamanho que um objeto ocupa em bytes. Por exemplo: 267 | 268 | ```python 269 | import sys 270 | 271 | lista_ex = [1, 2, 3, 'x', 'y', 'z', True, 3.14159] 272 | tupla_ex = (1, 2, 3, 'x', 'y', 'z', True, 3.14159) 273 | 274 | print(f'Tamanho da lista = {sys.getsizeof(lista_ex)}') # Tamanho da lista = 136 275 | print(f'Tamanho da tupla = {sys.getsizeof(tupla_ex)}') # Tamanho da tupla = 120 276 | ``` 277 | 278 | Como podemos observar, a tupla ocupa menos espaço em memória que uma lista. 279 | 280 | #### Comparando o Tempo 281 | 282 | A biblioteca [timeit](https://docs.python.org/3/library/timeit.html) nos fornece uma maneira simples de cronometrar pequenos trechos de código Python, podemos usá-la para medir a eficiência de estruturas de dados como listas e tuplas: 283 | 284 | ```python 285 | import timeit 286 | 287 | lista_teste = timeit.timeit(stmt='[1,2,3,4,5]', number=1_000_000) 288 | tupla_teste = timeit.timeit(stmt='(1,2,3,4,5)', number=1_000_000) 289 | 290 | print(f'Tempo da lista: {lista_teste}') # Tempo da lista: 0.11356729100225493 291 | print(f'Tempo da tupla: {tupla_teste}') # Tempo da tupla: 0.058329956023953855 292 | ``` 293 | 294 | Como podemos ver, as **tuplas** são uma estrutura de dados **imutável** e muito **rápida** que pode nos auxiliar bastante em nossos cálculos. 295 | -------------------------------------------------------------------------------- /content/dicionarios.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Dicionários' 3 | description: 'Aprenda sobre Dicionários' 4 | --- 5 | 6 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Dictionary.png) 7 | 8 | Os **dicionários** são encontrados em outros linguagens de programação como "memórias associativas" ou "matrizes associativas". Ao contrário das seqüências, que são indexadas por um intervalo de números, os dicionários são indexados por **chaves**, que podem ser de qualquer tipo imutável. 9 | 10 | Eles são uma coleção **não-ordenada** de pares de **chave** & **valor**, são normalmente usados quando temos uma grande quantidade de dados. 11 | 12 | Dicionários são otimizados para buscarmos dados e para isso, precisamos saber sua **chave**. 13 | 14 | Dicionários são definidos entre chaves `{}` onde cada item é um par na forma de **chave:valor**, separados por `,`, sendo a chave e o valor podendo ser de qualquer tipo. 15 | 16 | **Chaves**: 17 | 18 | - Devem ser **únicas** 19 | - Tipo **imutável** (int, float, string, tuple, bool) 20 | - Na verdade precisa de um objeto que seja *hashable*, mas imagine como imutável uma vez que todos os tipos imutáveis são *hashable* 21 | - Tenha cuidado com o tipo *float* como chave 22 | - Nenhuma ordem para chaves ou valores 23 | 24 | **Valores**: 25 | 26 | - Qualquer tipo (**imutável** e **mutável**) 27 | - Pode ser **duplicado** 28 | - Valores de dicionários podem ser listas, até mesmo outros dicionários 29 | 30 | Para compreendermos melhor o funcionamento dos dicionários, vamos definir alguns exemplos: 31 | 32 | ```python 33 | album = {'nome':'A Night at the Opera','artista':'Blind Guardian','lançamento':2002} 34 | print(type(album)) # 35 | print(album) # {'nome': 'A Night at the Opera', 'artista': 'Blind Guardian', 'lançamento': 2002} 36 | print(album['nome']) # A Night at the Opera 37 | print(album['artista']) # Blind Guardian 38 | print(album['lançamento']) # 2002 39 | ``` 40 | 41 | Também podemos definir um dicionário dessa forma, o que torna ele mais legível: 42 | 43 | ```python 44 | elemento = { 45 | "nome":"Ouro", 46 | "símbolo":"Au", 47 | "número atômico":79 48 | } 49 | ``` 50 | 51 | ### Acessando e Manipulando Dados 52 | 53 | Para acessarmos os itens do dicionário, precisamos nos referir a sua chave, por exemplo: 54 | 55 | ```python 56 | print(elemento["nome"]) # Ouro 57 | ``` 58 | 59 | Podemos também utilizar o método **get()** para acessarmos: 60 | 61 | ```python 62 | print(elemento.get("nome")) # Ouro 63 | ``` 64 | 65 | É possível alterar os valores de um dicionário, podemos fazê-lo da seguinte maneira: 66 | 67 | ```python 68 | elemento["nome"] = "Prata" 69 | elemento["símbolo"] = "Ag" 70 | elemento["número atômico"] = 47 71 | print(elemento) # {'nome': 'Prata', 'símbolo': 'Ag', 'número atômico': 47} 72 | ``` 73 | 74 | ### Imprimindo os Valores de um Dicionário 75 | 76 | Podemos usar o **for loop** para imprimir os elementos de um dicionário. 77 | 78 | ```python 79 | personagem = { 80 | "nome" : "Gandalf", 81 | "classe" : "Wizard", 82 | "ordem" : "Istari" 83 | } 84 | 85 | for key in personagem: # Percorre os valores do dicionário 86 | print(personagem[key]) # Imprime os valores do dicionário 87 | ``` 88 | 89 | Também podemos usar o método **values()** da seguinte forma: 90 | 91 | ```python 92 | for p in personagem.values(): # Percorre os valores do dicionário 93 | print(p) # Imprime os valores do dicionário 94 | ``` 95 | 96 | Além disso é possível percorrer tanto as **chaves** como os **valores**, usando a função **items()**: 97 | 98 | ```python 99 | for chave,valor in personagem.items(): # Percorre as chaves e os valores 100 | print(f'{chave} : {valor}') # Imprime as chaves e os valores 101 | ``` 102 | 103 | Caso seja necessário verificar a presença de uma **chave** no dicionário, podemos fazer o teste com a palavra-chave **in**: 104 | 105 | ```python 106 | print('nome' in personagem) # True 107 | ``` 108 | 109 | Também podemos testar pela presença de um determinado **valor** no dicionário: 110 | 111 | ```python 112 | print("Gandalf" in personagem.values()) # True 113 | ``` 114 | 115 | Assim como nas listas e tuplas, também podemos aplicar o método **len()** nos dicionários: 116 | 117 | ```python 118 | print(len(personagem)) # 3 119 | ``` 120 | 121 | ### Adicionando Itens ao Dicionário 122 | 123 | Para adicionarmos um novo item em nosso dicionário usamos uma nova chave e atribuimos um valor a ela 124 | 125 | ```python 126 | personagem['altura'] = 1.85 127 | print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard', 'Ordem': 'Istari', 'altura': 1.85} 128 | ``` 129 | 130 | ### Removendo Itens do Dicionário 131 | 132 | É possível também, de várias formas, remover os itens de um dicionário. 133 | 134 | Usando o método **pop()**, nos será retornado o item removido: 135 | 136 | ```python 137 | personagem.pop('altura') # 1.85 138 | print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard', 'Ordem': 'Istari'} 139 | ``` 140 | 141 | Usando o método **popitem()**, remove o último par de **chave**-**valores** adicionado de **personagem** e o retorna como uma tupla: 142 | 143 | ```python 144 | personagem.popitem() # ('Ordem', 'Istari') 145 | print(personagem) # {'nome': 'Gandalf', 'classe': 'Wizard'} 146 | ``` 147 | 148 | A palavra-chave **del** remove um item com a chave especificada: 149 | 150 | ```python 151 | del personagem['classe'] 152 | print(personagem) # {'nome': 'Gandalf'} 153 | ``` 154 | 155 | Além disso é possível deletar o dicionário por completo com **del**, tenha muita atenção, pois todos os dados serão perdidos. 156 | 157 | ```python 158 | del personagem 159 | print(personagem) # NameError: name 'personagem' is not defined 160 | ``` 161 | 162 | ### Construtor dict() 163 | 164 | Através do construtor **dict()** também é possível criarmos dicionários: 165 | 166 | ```python 167 | pessoa = dict(nome="Jesus", idade=33) 168 | print(pessoa) # {'nome': 'Jesus', 'idade': 33} 169 | ``` 170 | 171 | Uma outra maneira de atualizarmos os dados de um dicionário é com o uso do método **update()**: 172 | 173 | ```python 174 | pessoa.update({'nome':'Immanuel'}) 175 | print(pessoa) # {'nome': 'Immanuel', 'idade': 33} 176 | ``` 177 | 178 | ### Método clear() 179 | 180 | O método **clear()** nos permite esvaziar o dicionário por completo: 181 | 182 | ```python 183 | pessoa.clear() 184 | print(pessoa) # {} 185 | ``` 186 | 187 | ### Ordenando um Dicionário 188 | 189 | Vamos agora criar um dicionário chamado de **pokedex**, este será um pequeno registro de alguns pokémons, que iremos **ordernar** através de **[expressões lambda](https://python-reference.readthedocs.io/en/latest/docs/operators/lambda.html)**. 190 | 191 | Criando o Dicionário: 192 | 193 | ```python 194 | pokedex = [ 195 | {'nome':'pikachu','tipo':'elétrico'}, 196 | {'nome':'charizard','tipo':'fogo'}, 197 | {'nome':'bulbasaur','tipo':'planta'}, 198 | {'nome':'squirtle','tipo':'aquatico'} 199 | ] 200 | ``` 201 | 202 | Ordenando os pokémons por **tipo** através de uma expressão lambda: 203 | 204 | ```python 205 | ordenados = sorted(pokedex, key=lambda x: x['tipo']) 206 | print(ordenados) 207 | # [{'nome': 'squirtle', 'tipo': 'aquatico'}, {'nome': 'pikachu', 'tipo': 'elétrico'}, {'nome': 'charizard', 'tipo': 'fogo'}, {'nome': 'bulbasaur', 'tipo': 'planta'}] 208 | ``` 209 | 210 | ### Dicionários Comprehensions 211 | 212 | Supondo que tenhamos por exemplo duas listas e desejamos montar um dicionário através delas, podemos usar a técnica de **[comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions)** para executar tal tarefa. 213 | 214 | Para este exemplo, vamos primeiro iniciar duas listas e com elas, construíremos um dicionário: 215 | 216 | ```python 217 | autores = ['Aldous Huxley','George Orwell','Ray Bradbury','William Gibson'] 218 | livros = ['Brave New World','1984','Fahrenheit 451','Neuromancer'] 219 | 220 | autores_livros = {autor: livro for autor, livro in zip(autores, livros)} 221 | print(autores_livros) 222 | # {'Aldous Huxley': 'Brave New World', 'George Orwell': '1984', 'Ray Bradbury': 'Fahrenheit 451', 'William Gibson': 'Neuromancer'} 223 | ``` 224 | 225 | Um *dictionary comprehension* também pode conter o statement **if**, que pode ser usado para filtrarmos itens. 226 | 227 | Vejamos como podemos formar um dicionário apenas com números pares e seus respectivos quadrados: 228 | 229 | ```python 230 | quadrados_pares = {x: x*x for x in range(11) if x % 2 == 0} 231 | print(quadrados_pares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64, 10: 100} 232 | ``` 233 | 234 | ### Dicionários Aninhados 235 | 236 | Os dicionários são uma estrutura de dados muito flexível e nos permitem até mesmo guardar **dicionários dentro de um dicionário**, de forma que possamos acessá-los através de uma **chave**. Vejamos um exemplo para ilustrar: 237 | 238 | ```python 239 | jogos = { 240 | '1':{'nome':'castlevania','genero':'aventura'}, 241 | '2':{'nome':'super mario','genero':'aventura'}, 242 | '3':{'nome':'world of warcraft','genero':'MMORPG'} 243 | } 244 | 245 | print(jogos['2']) # {'nome': 'super mario', 'genero': 'aventura'} 246 | print(jogos.get('1')) # {'nome': 'castlevania', 'genero': 'aventura'} 247 | print(jogos['3']['nome']) # world of warcraft 248 | ``` 249 | 250 | ### Copiando um Dicionário 251 | 252 | Você não pode copiar um dicionário simplesmente digitando `copia_filme = filme`, porque: **copia_filme** será apenas uma referência para **filme**, e as alterações feitas em **filme** também serão feitas automaticamente em **copia_filme**. 253 | 254 | Uma maneira de copiarmos um dicionário é usando o método interno **copy()**: 255 | 256 | ```python 257 | filme = {'titulo':'Lord of the Rings','Gênero':'Aventura'} 258 | print(filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'} 259 | copia_filme = filme.copy() 260 | print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'} 261 | ``` 262 | 263 | Se eventualmente alterarmos o dicionário **filme**, a cópia não será afetada: 264 | 265 | ```python 266 | filme['Gênero'] = 'Fantasia' 267 | print(filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'} 268 | print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Aventura'} 269 | ``` 270 | 271 | Uma outra opção para copiarmos um dicionário é com o uso do método **dict()**, ao qual já vimos anteriormente. 272 | 273 | ```python 274 | copia_filme = dict(filme) 275 | print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'} 276 | filme['titulo'] = 'The Hobbit: An Unexpected Journey' 277 | print(filme) # {'titulo': 'The Hobbit: An Unexpected Journey', 'Gênero': 'Fantasia'} 278 | print(copia_filme) # {'titulo': 'Lord of the Rings', 'Gênero': 'Fantasia'} 279 | ``` 280 | 281 | ### Fibonacci com Dicionários 282 | 283 | Podemos utilizar o poder dos dicionários para otimizar uma função Fibonnaci e tornar seus resultados mais rápidos ao guardarmos os valores já computados em um **dicionário**. Esta técnica é conhecida como [Memoization](https://en.wikipedia.org/wiki/Memoization). 284 | 285 | ```python 286 | def fib_eficiente(n, d): 287 | if n in d: 288 | return d[n] 289 | else: 290 | resposta = fib_eficiente(n-1, d) + fib_eficiente(n-2, d) 291 | d[n] = resposta 292 | return resposta 293 | 294 | d = {1:1, 2:2} 295 | print(fib_eficiente(8, d)) # 34 296 | ``` 297 | 298 | Podemos concluir que os dicionários são uma estrutura de dados que nos oferece uma maneira eficaz de **guardar** e **buscar** os dados, considere a importância deles para usos no futuro. 299 | -------------------------------------------------------------------------------- /content/operadores.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Operadores' 3 | description: 'Introdução aos operadores do Python' 4 | --- 5 | 6 | **Operadores** são **símbolos especiais** capazes de executar computação **aritmética** ou **lógica**. 7 | 8 | Os operadores são usados para realizar operações em variáveis e valores. 9 | 10 | Existem diversos tipos de operadores em **Python**: 11 | 12 | - Operadores Aritméticos 13 | - Operadores de Atribuição 14 | - Operadores de Comparação 15 | - Operadores Lógicos 16 | - Operadores de Identidade 17 | - Operadores de Membros 18 | - Operadores Bitwise 19 | 20 | Vejamos então como eles funcionam em mais detalhes. 21 | 22 | ## Operadores Aritméticos 23 | 24 | Operadores aritméticos são usados com valores numéricos para realizar operações matemáticas comuns: 25 | 26 | | Operador | Descrição | Exemplo | 27 | |----------|----------------------------------------------------------------------------|---------| 28 | | + | Adiciona dois operandos | 2+5 | 29 | | - | Subtrai o operando da direita pelo da esquerda | 7-2 | 30 | | * | Multiplica dois operandos | 3*3 | 31 | | / | Divide o operando da esquerda pelo da direita | 3/2 | 32 | | % | Módulo, resto da divisão do operando da esquerda pelo da direita | 10%3 | 33 | | // | Divisão arredondada, esta divisão retorna um número inteiro | 3//2 | 34 | | ** | Expoente, operando a esquerda elevado à potência do operando a direita | 2**32 | 35 | 36 | Por exemplo: 37 | 38 | ```python 39 | x = 10 40 | y = 6 41 | z = 6.0 42 | 43 | print("x + y = ", x+y) # Nos resulta 16 44 | print("x - y = ", x-y) # Nos resulta 4 45 | print("x * y = ", x*y) # Nos resulta 60 46 | print("x / y = ", x/y) # Nos resulta 1.6666666666666667 47 | print("x / z = ", x/z) # Nos resulta 1.6666666666666667 48 | print("x // y = ", x//y) # Nos resulta 1 49 | print("x ** y = ", x**y) # Nos resulta 1000000 50 | ``` 51 | 52 | Observe que definimos a variável **z** com o valor **6.0**, um número ponto flutuante, de forma que Python possa nos trazer um resultado ponto flutuante no momento de fazermos a divisão do valor de **x** por **z**. 53 | 54 | ## Operadores de Atribuição 55 | 56 | Operadores de atribuição são usados para atribuir valores a variáveis: 57 | 58 | | Operador | Exemplo 1 | Exemplo 2 | 59 | |----------|-----------|------------| 60 | | = | x = 3 | x = 3 | 61 | | += | x += 3 | x = x + 3 | 62 | | -= | x -= 3 | x = x - 3 | 63 | | *= | x *= 3 | x = x * 3 | 64 | | /= | x /= 3 | x = x / 3 | 65 | | %= | x %= 3 | x = x % 3 | 66 | | //= | x //= 3 | x = x // 3 | 67 | | **= | x **= 3 | x = x ** 3 | 68 | | &= | x &= 3 | x = x & 3 | 69 | | \|= | x \|= 3 | x = x \| 3 | 70 | | ^= | x ^= 3 | x = x ^ 3 | 71 | | >>= | x >>= 3 | x = x >> 3 | 72 | | <<= | x <<= 3 | x = x << 3 | 73 | 74 | Vejamos um simples exemplo: 75 | 76 | ```python 77 | a = 1 78 | a += 3 79 | 80 | print(a) # 4 81 | ``` 82 | 83 | ## Operadores de Comparação 84 | 85 | Operadores de comparação são usados para comparar valores. Retornarão **True** ou **False** de acordo com a condição. 86 | 87 | | Operador | Descrição | Exemplo | 88 | |----------|--------------------------------------------------------------------------------------|---------| 89 | | > | Maior que - True se o operando a esquerda for maior que o da direita | x > y | 90 | | < | Menor que - True se o operando a esquerda for menor que o da direita | x < y | 91 | | == | Igual - True se ambos os operandos forem iguais | x == y | 92 | | != | Não Igual - True se os operandos forem diferentes | x != y | 93 | | >= | Maior que ou Igual - True se o operando da esquerda for maior ou igual ao da direita | x >= y | 94 | | <= | Menor que ou Igual - True se o operando da esquerda for menor ou igual ao da direita | x <= y | 95 | 96 | Vejamos alguns exemplos de comparações: 97 | 98 | ```python 99 | x = 12 100 | y = 3 101 | 102 | print(x>y) # True 103 | print(x=y) # True 107 | print(x<=y) # False 108 | ``` 109 | 110 | ## Operadores Lógicos 111 | 112 | Operadores Lógicos são usados para combinar **comandos condicionais**. 113 | 114 | | Operador | Descrição | Exemplo | 115 | |----------|-------------------------------------------------------------------------|------------------| 116 | | and | Retorna True se ambos os comandos são verdadeiros | x < y and x < 10 | 117 | | or | Retorna True se um dos comandos é verdadeiro | x < y or x > 3 | 118 | | not | Reverte o resultado, retorna False se o resultado for True e vice-versa | not(x > 10) | 119 | 120 | Vamos considerar então alguns exemplos com operadores lógicos: 121 | 122 | ```python 123 | n1, n2, n3 = 3, 6, 7 124 | 125 | print(n1 < n2 and n1 < n3) # True 126 | print(n1 == n2 or n3 == n2) # False 127 | print(not True) # False 128 | ``` 129 | 130 | ## Operadores de Identidade 131 | 132 | Operadores de identidade são usados para comparar os objetos, não se são iguais, mas se eles forem realmente o mesmo objeto, com o mesmo local de memória. 133 | 134 | **is** e **is not** são operadores de identidade em **Python**, eles são usados para checar se dois valores (ou variáveis) estão localizados na mesma área de memória, *duas variáveis iguais não significam que são idênticas!* 135 | 136 | | Operador | Descrição | 137 | |----------|----------------------------------------------------------------------| 138 | | is | True se os operandos são idênticos (referem ao mesmo objeto) | 139 | | is not | True se os operandos não são idênticos (não referem ao mesmo objeto) | 140 | 141 | Exemplo com números: 142 | 143 | ```python 144 | x = 1 145 | y = 1 146 | 147 | print(x is y) # True 148 | print(x is not y) # False 149 | ``` 150 | 151 | Exemplo com strings: 152 | 153 | ```python 154 | a = "cachorro" 155 | b = "cachorro" 156 | 157 | print(a is b) # True 158 | print(a is not b) # False 159 | ``` 160 | 161 | Exemplo com listas: 162 | 163 | ```python 164 | z = [1,2,3] 165 | k = [1,2,3] 166 | 167 | print(z is k) # False 168 | print(z is not k) # True 169 | ``` 170 | 171 | Perceba aqui que **x** e **y** são inteiros do mesmo valor, então eles são iguais e idênticos, o mesmo vale 172 | para **a** e **b** (strings). Porém o mesmo não ocorre com **z** e **k**, que são iguais, porem não idênticos, isso porque o interpretador localiza eles separadamente em memória, mesmo eles sendo iguais. 173 | 174 | ## Operadores de Membros 175 | 176 | Operadores de membros são usados para testar se uma sequência é apresentada em um objeto. 177 | 178 | | Operador | Descrição | Exemplo | 179 | |----------|-----------------------------------------------------------------|-------------------| 180 | | in | Retorna True se o valor/variável é encontrado na sequência | "c" in "cachorro" | 181 | | not in | Retorna True se o valor/variável não está presenta na sequência | 1 not in [1,2,3] | 182 | 183 | Exemplo básico: 184 | 185 | ```python 186 | a = [1,2,3] 187 | b = "Guilherme" 188 | 189 | print(1 in a) # Retorna True, pois 1 se encontra na lista a 190 | print("o" in b) # Retorna False, pois o não se encontra na string b 191 | ``` 192 | 193 | ## Operadores Bitwise 194 | 195 | Os operadores Bitwise atuam nos operandos como se eles fossem strings ou dígitos binários, eles executam operações **bit** por **bit**, por isso levam o nome **Bitwise**. 196 | 197 | Considere o valor 2 que é representado por **10** em binário e 7 que é representado por **111**. 198 | 199 | Vamos utilizar a função **bin()** que nos retorna uma string binária: 200 | 201 | ```python 202 | x = 10 203 | y = 4 204 | 205 | print(bin(x)) # 0b1010 206 | print(bin(y)) # 0b100 207 | ``` 208 | 209 | Adaptando-os, temos **(x = 0000 1010)** em binário e **(y = 0000 0100)** em binário, vamos aos operadores: 210 | 211 | | Operador | Descrição | Exemplo | 212 | |----------|---------------------|-------------------------| 213 | | & | Bitwise AND | x & y = 0 (0000 0000) | 214 | | \| | Bitwise OR | x \| y = 14 (0000 1110) | 215 | | ~ | Bitwise NOT | ~x = -11 (1111 0101) | 216 | | ^ | Bitwise XOR | x ^ y = 14 (0000 1110) | 217 | | >> | Bitwise right shift | x >> 2 = 2 (0000 0010) | 218 | | << | Bitwise left shift | x << 2 = 40 (0010 1000) | 219 | 220 | ## Precedência de Operadores 221 | 222 | Vamos agora considerar a seguinte expressão: 223 | 224 | ```python 225 | print(3 + 4 * 5) # 23 226 | ``` 227 | 228 | Há ambigüidade nesta expressão. O Python deve realizar a adição `3 + 4` primeiro e depois multiplicar a soma por `5`? Ou a multiplicação de `4 * 5` deve ser realizada primeiro? 229 | 230 | Uma vez que nosso resultado é **23**, significa que Python optou por multiplicar primeiro e depois realizar a adição, este é o procedimento padrão algébrico, encontrado universalmente em todas as linguagens de programação. 231 | 232 | Todos os operadores suportados por Python têm precedência. Em uma expressão, todos os operadores de maior precedência são executados primeiro. Depois que esses resultados são obtidos, os operadores da próxima precedência mais alta são executados. Então continua-se, até que a expressão seja totalmente avaliada. Quaisquer operadores de igual precedência são executados da **esquerda** para a **direita**. 233 | 234 | A tabela a seguir apresenta a ordem de precedência dos operadores Python do menor ao maior: 235 | 236 | | | Operador | Descrição | 237 | |---|---|---| 238 | | menor precedência | or | Boolean OR | 239 | | | and | Boolean AND | 240 | | | not | Boolean NOT | 241 | | | ==, !=, <, <=, >, >=, is, is not | Comparações, Identidade | 242 | | | \| | Bitwise OR | 243 | | | ^ | Bitwise XOR | 244 | | | & | Bitwise AND | 245 | | | <<, >> | Bit Shifts | 246 | | | +, - | Adição, Subtração | 247 | | | *, /, //, % | Multiplicação, Divisão, Floor Division, Modulus | 248 | | | +x, -x, ~x | Unário Positivo, Unário Negativo, Bitwise Negation | 249 | | maior precedência | ** | Exponenciação | 250 | 251 | Os operadores na parte superior da tabela têm a precedência mais baixa e aqueles na parte inferior da tabela têm a mais alta. Quaisquer operadores na mesma linha da tabela têm precedência igual. 252 | 253 | A precedência do operador pode ser substituída usando parênteses. As expressões entre parênteses são sempre executadas primeiro, antes das expressões que não estão entre parênteses. Por exemplo: 254 | 255 | ```python 256 | print(3 + 3 * 5) # 18 257 | print((3 + 3) * 5) # 30 258 | ``` 259 | 260 | Lembre sempre que os operadores tem um papel fundamental na programação e que devemos entender o seu funcionamento de maneira plena, *faça experimentos e divirta-se com os cálculos*! 261 | -------------------------------------------------------------------------------- /content/sintaxe.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Sintaxe' 3 | description: 'Introdução a Sintaxe da linguagem Python' 4 | --- 5 | 6 | Python foi originalmente desenvolvido como uma linguagem de ensino, mas sua facilidade de uso e sintaxe limpa levaram-no a ser adotado por iniciantes e especialistas. 7 | 8 | A **sintaxe** da linguagem de programação Python é o conjunto de regras que define como um programa Python será escrito e interpretado (tanto pelo sistema de execução quanto por leitores humanos). 9 | 10 | ## Palavras-chave em **Python** 11 | 12 | As palavras-chave são as palavras reservadas pela linguagem **Python**, nós não podemos utilizar essas palavras para nomear nossas **[variáveis](https://pt.wikipedia.org/wiki/Variável_(programação))**, **[funções](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)** ou qualquer outro identificador, elas são usadas para definir a sintaxe e a estrutura da linguagem **Python**, vale lembrar que as palavras-chave são **case sensitive** e devem ser escritas dessa maneira. 13 | 14 | A seguir mostramos a lista de todas as palavras-chave: 15 | 16 | | **Nome** | **Descrição** | 17 | |----------|:-------------------------------------------------------------------------------------------------:| 18 | | and | operador lógico "e" | 19 | | as | capaz de criar um **[alias](https://pt.wikipedia.org/wiki/Alias_(comando))** | 20 | | assert | usado para **[debugging](https://www.inf.pucrs.br/flash/progbio/aulas/seq/build/progbio/WhatisDebugging.html)** | 21 | | async | usado para escrever aplicações **[asyncio](https://docs.python.org/3/library/asyncio-task.html)** | 22 | | await | usado para escrever aplicações **[asyncio](https://docs.python.org/3/library/asyncio-task.html)** | 23 | | break | para sair de um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 24 | | class | define uma **[classe](https://pt.wikipedia.org/wiki/Classe_(programação))** | 25 | | continue | continua para a nova iteração do **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 26 | | def | define uma **[função](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)** | 27 | | del | deleta um **[objeto](https://pt.wikipedia.org/wiki/Objeto_(ciência_da_computação))** | 28 | | elif | usado em **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)**, como else e if | 29 | | else | usado em **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)** | 30 | | except | usado com **[exceções](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)**, para tratar possíveis erros | 31 | | False | Valor **[booleano](https://pt.wikipedia.org/wiki/Booleano)**, resulta de operações de comparação | 32 | | finally | utilizado com **[exceções](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)**, um bloco de código que executará independente de ter uma exceção ou não | 33 | | for | usado para criar um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 34 | | from | para importar partes específicas de um **[módulo](https://pt.wikipedia.org/wiki/Módulo_de_um_programa)** | 35 | | global | declara uma **[variável global](https://pt.wikipedia.org/wiki/Variável_global)** | 36 | | if | usado para **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)** | 37 | | import | usado para importar **[módulos](https://pt.wikipedia.org/wiki/Módulo_de_um_programa)** | 38 | | in | capaz de checar se um valor está presente em uma lista, tupla, etc | 39 | | is | testa se duas **[variáveis](https://pt.wikipedia.org/wiki/Variável_(programação))** são iguais | 40 | | lambda | cria uma **[função anônima](https://github.com/the-akira/Python-Iluminado/blob/master/17.Lambda.md)** | 41 | | None | representa um valor **[null](https://pt.wikipedia.org/wiki/Null_(programação))** | 42 | | nonlocal | declara uma **[variável](https://pt.wikipedia.org/wiki/Variável_(programação))** não-local | 43 | | not | **[operador lógico](https://pt.wikipedia.org/wiki/Operador_lógico)** de negação | 44 | | or | **[operador lógico](https://pt.wikipedia.org/wiki/Operador_lógico)** "ou" | 45 | | pass | comando null, um comando que não faz nada | 46 | | raise | dispara um **[exceção](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)** | 47 | | return | para sair de uma **[função](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)** e retornar um valor | 48 | | True | Valor **[booleano](https://pt.wikipedia.org/wiki/Booleano)**, resulta de operações de comparação | 49 | | try | Comando de try, usado em conjunto com except | 50 | | while | Cria um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** while | 51 | | with | usado para simplificar a lida com **[exceções](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)** | 52 | | yield | finaliza uma **[função](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)**, retorna um **[gerador](https://pt.wikipedia.org/wiki/Gerador_(ciência_da_computação))** | 53 | 54 | Obtendo as palavras-chave através do **interpretador** Python: 55 | 56 | ```python 57 | >>> import keyword 58 | >>> print(keyword.kwlist) 59 | ``` 60 | 61 | Veja que nos é retornado uma **lista** (Estrutura de Dados que veremos com mais detalhes em breve) com todas as palavras-chave da linguagem Python. 62 | 63 | ``` 64 | ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] 65 | ``` 66 | 67 | *Bastante informação, não?* Talvez muito do que foi mostrado não faça sentido para você, porém fique tranquilo que veremos todas as palavras-chave com detalhe, até que você fique acostumado com elas! 68 | 69 | ## Identificadores 70 | 71 | Os identificadores são nomes dados às entidades como **[variáveis](https://pt.wikipedia.org/wiki/Variável_(programação))**, **[funções](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)**, **[classes](https://pt.wikipedia.org/wiki/Classe_(programação))**, etc, eles nos ajudam a diferenciar uma entidade da outra. 72 | 73 | ## Regras 74 | 75 | Identificadores podem ser escritos com uma combinação de **letras em lowercase (a até z)** ou **uppercase (A até Z)** ou **dígitos (0 até 9)** ou um **underline (_)**. Nomes como **minhaClasse**, **variavel_1** e **minha_variavel** são exemplos válidos de identificadores. 76 | 77 | Variáveis são **case sensitive** (idade, Idade e IDADE são três variáveis diferentes) 78 | Identificadores **não podem começar com dígitos:** 13variavel é inválido, porém variavel13 é aceito! 79 | 80 | Palavras-chave jamais podem ser usadas como identificadores! 81 | 82 | ## Indentação 83 | 84 | Enquanto em outras linguagens de programação a **[indentação](https://pt.wikipedia.org/wiki/Indentação)** é usada apenas para tornar o código mais legível, em **Python** ela é importantíssima, **Python** usa a indentação para indicar blocos de código, por exemplo: 85 | 86 | ```python 87 | vida = 100 88 | 89 | if vida > 0: 90 | print("Você está vivo") 91 | ``` 92 | 93 | Caso você não utilize a indentação correta, Python irá disparar um erro. 94 | 95 | Algumas regras de indentação: 96 | 97 | - Use dois pontos `:` para iniciar um bloco e pressione `[Enter]`. 98 | - Todas as linhas em um bloco devem usar a mesma indentação, seja com espaços ou `[tab]`. 99 | - Python recomenda quatro espaços como indentação para tornar o código mais legível. Não misture espaço e `[tab]` no mesmo bloco. 100 | 101 | Você pode configurar seu editor de texto para a tecla `[tab]` indentar uma quantidade **x** de espaço. 102 | 103 | ## Comentários 104 | 105 | **Python** tem a capacidade de comentários para que seja mais fácil de lermos os códigos de outros programadores, melhora muito a comunicação! 106 | 107 | Comentários começam com `#`, por exemplo: 108 | 109 | ```python 110 | # Este é um comentário 111 | print("Códigos comentados são muito mais fáceis de serem compreendidos") 112 | ``` 113 | 114 | **Python** também suporta [docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html), que são comentários que podem extender até mais linhas, veja: 115 | 116 | ```python 117 | """ 118 | Este é um comentário 119 | que abrange várias 120 | linhas do programa 121 | """ 122 | print("Procure sempre comentar o seu código") 123 | ``` 124 | 125 | ## Statements 126 | 127 | As instruções em Python geralmente terminam com uma nova linha. Python, entretanto, permite o uso do caractere de continuação de linha (`\`) para indicar que a linha deve continuar. Por exemplo: 128 | 129 | ```python 130 | total = 3 + \ 131 | 5 + \ 132 | 7 133 | print(total) # 15 134 | ``` 135 | 136 | O ponto e vírgula (`;`) permite várias instruções em uma única linha, visto que nenhuma instrução inicia um novo bloco de código. Aqui está uma amostra que ilustra esta ideia: 137 | 138 | ```python 139 | x, y = 9, 3; z = x * y; print(f'{x} x {y} = {z}') 140 | # 9 x 3 = 27 141 | ``` 142 | 143 | Para saber mais detalhes específicos e técnicos sobre boas práticas de estilo de programação em Python, recomendamos que você visite e leia [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) 144 | -------------------------------------------------------------------------------- /content/xml.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'XML' 3 | description: 'Aprenda a trabalhar com arquivos XML em Python' 4 | --- 5 | 6 | **[XML](https://en.wikipedia.org/wiki/XML)** se refere a *"Extensible Markup Language"*, é uma **[markup language](https://en.wikipedia.org/wiki/Markup_language)** que define um conjunto de regras para a codificação de documentos em um formato tanto legível por humanos quanto por máquina. 7 | 8 | Com similaridades ao famoso **HTML**, sua proposta principal é guardar e transportar dados, sendo uma linguagem auto-descritiva. **XML** funciona como uma estrutura de árvore que é fácil de interpretar e suporta hierarquia. 9 | 10 | Os objetivos de design do XML enfatizam a simplicidade, generalidade e usabilidade na Internet. É um formato de dados textual com forte suporte via [Unicode](https://en.wikipedia.org/wiki/Unicode) para diferentes idiomas humanos. Embora o design de XML se concentre em documentos, a linguagem é amplamente utilizada para a representação de estruturas de dados arbitrárias, como aquelas usadas em [serviços web](https://en.wikipedia.org/wiki/Web_service). 11 | 12 | **Documentos XML** possuem seções chamadas de **elementos**, sendo definidos por uma *tag de abertura e fechamento*. Tag é um constructo de markup que começa com `<` e termina com `>`. Os caracteres entre a tag de abertura e fechamento, caso tenha algum, é o conteúdo do elemento. 13 | 14 | Elementos podem conter markup, incluindo outros elementos, que nesse caso, são chamados de filhos. O elemento de maior nível é chamado de **root**, do inglês, raiz em português, esse seria o elemento que **engloba** todos os outros. *Atributos são pares de nome-valor* que existem dentro de uma tag de abertura ou uma tag de elemento vazio. Um atributo **XML** só pode ter um único valor e cada atributo pode aparecer no máximo uma vez em cada elemento. 15 | 16 | Para entendermos melhor o **XML**, vamos utilizar o arquivo [livros.xml](https://github.com/the-akira/Python-Iluminado/blob/master/Arquivos/livros.xml) como exemplo: 17 | 18 | ```xml 19 | 20 | 21 | 22 | Orwell, George 23 | Nineteen Eighty-Four: A Novel 24 | Dystopian 25 | 1949-06-08 26 | Thematically, Nineteen Eighty-Four centres on the consequences of totalitarianism, mass surveillance, and repressive regimentation of persons and behaviours within society. 27 | 28 | 29 | Huxley, Aldous 30 | Brave New World 31 | Dystopian 32 | 1932-12-16 33 | Largely set in a futuristic World State, whose citizens are environmentally engineered into an intelligence-based social hierarchy, the novel anticipates huge scientific advancements in reproductive technology, sleep-learning, psychological manipulation and classical conditioning that are combined to make a dystopian society which is challenged by only a single individual: the story's protagonist. 34 | 35 | 36 | Huxley, Aldous 37 | The Doors of Perception 38 | Psychology 39 | 1954-11-17 40 | The Doors of Perception provoked strong reactions for its evaluation of psychedelic drugs as facilitators of mystical insight with great potential benefits for science, art, and religion. 41 | 42 | 43 | Gibson, William 44 | Neuromancer 45 | Cyberpunk 46 | 1984-07-01 47 | Set in the future, the novel follows Henry Case, a washed-up computer hacker who is hired for one last job, which brings him up against a powerful artificial intelligence. 48 | 49 | 50 | Erickson, Jon 51 | Hacking: The Art of Exploitation 52 | Computer Security 53 | 2003-09-10 54 | Hacking: The Art of Exploitation is a book by Jon "Smibbs" Erickson about computer security and network security. 55 | 56 | 57 | Chollet, François 58 | Deep Learning with Python 59 | Machine Learning 60 | 2017-11-02 61 | Deep Learning with Python introduces the field of deep learning using the Python language and the powerful Keras library. Written by Keras creator and Google AI researcher François Chollet, this book builds your understanding through intuitive explanations and practical examples. 62 | 63 | 64 | Kant, Immanuel 65 | Critique of Pure Reason 66 | Philosophy 67 | 1787-11-02 68 | The Critique of Pure Reason is a book by the German philosopher Immanuel Kant, in which the author seeks to determine the limits and scope of metaphysics. 69 | 70 | 71 | Schopenhauer, Arthur 72 | The World as Will and Representation 73 | Philosophy 74 | 1818-12-06 75 | Taking the transcendental idealism of Immanuel Kant as his starting point, Schopenhauer argues that the world we experience around us—the world of objects in space and time and related in causal ways—exists solely as 'representation' (Vorstellung) dependent on a cognizing subject, not as a world that can be considered to exist in itself (independently of how it appears to the subject’s mind). 76 | 77 | 78 | ``` 79 | 80 | Como podemos ver, ele é fácil de compreender e legível, assim como os arquivos JSON, agora vamos começar a trabalhar com ele em **Python**, para isso vamos usar o módulo **[xml.etree.ElementTree](https://docs.python.org/3/library/xml.etree.elementtree.html)**, porém esteja atento que esse módulo *não é seguro contra dados maliciosos*, então esteja atento na segurança dos dados que você vai processar. 81 | 82 | O módulo **xml.etree.ElementTree** implementa uma API simples e eficiente para analisar e criar dados XML. 83 | 84 | Para trabalharmos com este módulo, é necessário apenas importá-lo, sem a necessidade de instalação. Vamos nos referir a ele apenas como **et** para ficar mais simples para trabalharmos: 85 | 86 | ```python 87 | import xml.etree.ElementTree as et 88 | ``` 89 | 90 | Para carregar o nosso arquivo, vamos utilizar o método **parse()**: 91 | 92 | ```python 93 | arquivo = et.parse('livros.xml') 94 | print(arquivo) 95 | # 96 | ``` 97 | 98 | Observe que nos é retornado um objeto **ElementTree**, que representa respectivamente uma árvore de elementos XML. Para obtermos a raiz (root) desta árvore, podemos usar o método **getroot()**: 99 | 100 | ```python 101 | raiz = arquivo.getroot() 102 | print(raiz) # 103 | print(raiz.tag) # 'catalog' 104 | ``` 105 | 106 | Como podemos ver, temos um objeto **Element** com o nome 'catalog', que representa o nosso catálogo de livros, a raiz de nossa árvore, com o atributo **tag** podemos acessar este valor. 107 | 108 | Uma vez que temos a raiz, podemos por exemplo iterar sob os children nodes, que são as tags filhas respectivamente: 109 | 110 | ```python 111 | for filhas in raiz: 112 | print(filhas.tag, filhas.attrib) 113 | 114 | # book {'id': 'bk101'} 115 | # book {'id': 'bk102'} 116 | # book {'id': 'bk103'} 117 | # book {'id': 'bk104'} 118 | # book {'id': 'bk105'} 119 | # book {'id': 'bk106'} 120 | # book {'id': 'bk107'} 121 | # book {'id': 'bk108'} 122 | ``` 123 | 124 | Neste exemplo específico, estamos obtendo o nome das tags filhas e seus respectivos atributos. 125 | 126 | As tags filhas são **encadeadas**, e para acessarmos seus valores específicos por índice, usamos esta notação: 127 | 128 | ```python 129 | print(raiz[0][0].text) # Orwell, George 130 | print(raiz[1][1].text) # Brave New World 131 | ``` 132 | 133 | Agora vamos utilizar o método **findall()** que nos permite procurar por **tags** que são filhas diretas do elemento atual que estamos usando. Além disso, temos também o método **find()** que procura o primeiro filho com uma tag particular e **Element.text** que acesso o conteúdo de texto do elemento. 134 | 135 | ```python 136 | for filhas in raiz.findall('book'): 137 | autor = filhas.find('author').text 138 | titulo = filhas.find('title').text 139 | print(f'Autor: {autor} | Título: {titulo}') 140 | 141 | # Autor: Orwell, George | Título: Nineteen Eighty-Four: A Novel 142 | # Autor: Huxley, Aldous | Título: Brave New World 143 | # Autor: Huxley, Aldous | Título: The Doors of Perception 144 | # Autor: Gibson, William | Título: Neuromancer 145 | # Autor: Erickson, Jon | Título: Hacking: The Art of Exploitation 146 | # Autor: Chollet, François | Título: Deep Learning with Python 147 | # Autor: Kant, Immanuel | Título: Critique of Pure Reason 148 | # Autor: Schopenhauer, Arthur | Título: The World as Will and Representation 149 | ``` 150 | 151 | Também podemos usar o método **iter()** que nos ajuda a iterar sob a árvore XML. Por exemplo: 152 | 153 | ```python 154 | descricoes = [d.text for d in raiz.iter('description')] 155 | print(descricoes[0]) 156 | # Thematically, Nineteen Eighty-Four centres on the consequences of totalitarianism, mass surveillance, and repressive regimentation of persons and behaviours within society. 157 | ``` 158 | 159 | ElementTree fornece uma maneira simples de construir documentos XML e gravá-los em arquivos. O método **write()** serve a esse propósito. 160 | 161 | Uma vez criado, um objeto Element pode ser manipulado alterando diretamente seus campos (como Element.text), adicionando e modificando atributos (método **set()**), bem como adicionando novos filhos (por exemplo, com **append()**). 162 | 163 | Imagine que queremos atualizar o gênero do livro **Neuromancer** para **Science Fiction**, podemos fazê-lo com o auxílio dos métodos **find()** e **findall()** e com um simples `if` testamos pela existência do gênero atual e o substituímos pelo novo, e através do método **set()** nós adicionamos um atributo `atualizado` para esta tag ``. 164 | 165 | ```python 166 | for genre in raiz.findall('book'): 167 | genero = genre.find('genre') 168 | if genero.text == 'Cyberpunk': 169 | genero.text = 'Science Fiction' 170 | genero.set('atualizado','sim') 171 | print(genero.text) 172 | 173 | arquivo.write('novo_livros.xml') 174 | ``` 175 | 176 | Finalmente, com o método **write()** salvamos os novos dados em um novo arquivo. 177 | 178 | Também podemos remover elementos usando o método **remove()**. Se quisermos por exemplo remover o elemento ``, podemos usar o método **findall()** para iterar sob todos os elementos livros e buscar especificamente o elemento **publish_date** e removê-lo com o método **remove()**. Novamente podemos salvar as alterações em um novo arquivo com **write()**. 179 | 180 | ```python 181 | for book in raiz.findall('book'): 182 | publish_date = book.find('publish_date') 183 | book.remove(publish_date) 184 | 185 | arquivo.write('new_livros.xml') 186 | ``` 187 | 188 | Essa foi uma introdução básica ao XML com Python, embora já não esteja tão popular como no passado por conta do poderoso JSON, é necessário que entendamos como funciona a estrutura do arquivo XML e se necessário como manipulá-lo. 189 | -------------------------------------------------------------------------------- /content/json.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'JSON' 3 | description: 'Aprenda a trabalhar com dados JSON' 4 | --- 5 | 6 | Na computação, **[JSON](https://www.json.org/)** ou **Javascript Object Notation** é um padrão aberto de formato de arquivo que utiliza textos legíveis para humanos para transmistir objetos de dados que consistem de *pares de atributos-valores* e tipos de dados **array** (ou qualquer outro valor serializável), é um formato de dados de uso muito comum para comunicação *asíncrona de cliente-servidor*. 7 | 8 | É importante destacar, que embora JSON carregue Javascript no seu nome, ele é independente e vale para qualquer linguagem de programação. 9 | 10 | Os tipos básicos de dados do JSON são: 11 | 12 | - **Number**: Um número decimal com sinal que pode conter uma parte fracionária e pode usar a notação exponencial **E**, mas não pode incluir não-números como **NaN**. O formato não faz distinção entre integer e floating-point. 13 | - **String**: Uma sequência de zero ou mais caracteres Unicode. Strings são delimitadas com aspas duplas e oferecem suporte a uma sintaxe de escape de barra invertida. 14 | - **Boolean**: Um valor `true` ou `false` 15 | - **Array**: Uma lista ordenada de zero ou mais valores, cada um dos quais pode ser de qualquer tipo. Arrays usam notação de colchetes com elementos separados por vírgula. 16 | - **Object**: Uma coleção de pares **nome-valor** onde os nomes (também chamados de chaves) são strings. Os objetos têm o objetivo de representar arrays associativos, onde cada chave é única dentro de um objeto. Os objetos são delimitados por chaves e usam vírgulas `,` para separar cada par, enquanto dentro de cada par o caractere `:` separa a **chave** ou **nome** de seu **valor**. 17 | - **null**: Um valor vazio, utilizando a palavra `null` 18 | 19 | Para entendermos melhor o **JSON**, vamos definir um arquivo `pessoa.json` que descreverá uma pessoa: 20 | 21 | ```javascript 22 | { 23 | "primeiroName": "Miguel", 24 | "segundoName": "Arcanjo", 25 | "estaVivo": true, 26 | "idade": 27, 27 | "endereço": { 28 | "rua": "Rua Alfa 33", 29 | "cidade": "São Paulo", 30 | "estado": "SP", 31 | "codigoPostal": "1321-32423" 32 | }, 33 | "numerosTelefones": [ 34 | { 35 | "tipo": "casa", 36 | "numero": "212 555-1234" 37 | }, 38 | { 39 | "tipo": "escritorio", 40 | "numero": "646 555-4567" 41 | }, 42 | { 43 | "tipo": "celular", 44 | "numero": "123 456-7890" 45 | } 46 | ], 47 | "criancas": [], 48 | "cônjuge": null 49 | } 50 | ``` 51 | 52 | Como podermos ver, **JSON** é bastante legível e acessível, fazendo com que seja excelente para estruturarmos dados, nesse caso, veja que temos um objeto **pessoa**. 53 | 54 | Dentro do objeto pessoas temos diversos atributos: 55 | 56 | - **primeiroName**: String representando o primeiro nome da pessoa 57 | - **segundoName**: String representando o sobrenome da pessoa 58 | - **estaVivo**: Boolean representando se a pessoa está viva ou não 59 | - **idade**: Number integer representando a idade da pessoa 60 | - **endereço**: Um objeto com quatro atributos (rua, cidade, estado, codigoPostal) representando o endereço da pessoa 61 | - **numerosTelefones**: Um array contendo três objetos, representando os telefones da pessoa 62 | - **criancas**: Um array representando as crianças da pessoa, neste exemplo ele está vazio 63 | - **cônjuge**: Campo representando se a pessoa é casada, neste exemplo está `null` 64 | 65 | Para utilizarmos **JSON** em **Python**, contamos com o módulo **json**, que podemos importá-lo facilmente, sem a necessida de instalação: 66 | 67 | ```python 68 | import json 69 | ``` 70 | 71 | ## Parse de JSON, Convertendo JSON para Python 72 | 73 | Em Python, caso tenhamos uma string JSON, nós usamos o método **json.loads()** para fazer o **parse** e convertermos em um dicionário para que seja mais fácil de trabalharmos com os dados. 74 | 75 | Veja que além do arquivo `.json`, também podemos ter JSON armazenado como uma string: 76 | 77 | ```python 78 | import json 79 | 80 | pessoa = '{ "nome":"Rafael", "idade":29, "cidade":"São Paulo"}' 81 | 82 | pessoa_dict = json.loads(pessoa) 83 | print(type(pessoa_dict)) # 84 | print(pessoa_dict) # {'nome': 'Rafael', 'idade': 29, 'cidade': 'São Paulo'} 85 | print(pessoa_dict['idade']) # 29 86 | ``` 87 | 88 | ## Convertendo Python para JSON 89 | 90 | Se quisermos, também podemos converter um objeto de Python em uma string JSON, para esta tarefa vamos usar o método **json.dumps()**. 91 | 92 | Vamos definir um dicionário Python e fazer sua conversão: 93 | 94 | ```python 95 | import json 96 | 97 | pessoa = { 98 | "nome": "Gabriel", 99 | "idade": 27, 100 | "país": "Brasil" 101 | } 102 | 103 | pessoa_json = json.dumps(pessoa) # 104 | print(pessoa_json) # {"nome": "Gabriel", "idade": 27, "pa\u00eds": "Brasil"} 105 | ``` 106 | 107 | Perceba que ele não nos retornou os dados na codificação correta, para obtermos os dados em UTF-8, devemos setar o atributo **ensure_ascii** como `False`: 108 | 109 | ```python 110 | pessoa_json = json.dumps(pessoa, ensure_ascii=False) 111 | print(pessoa_json) # '{"nome": "Gabriel", "idade": 27, "país": "Brasil"}' 112 | ``` 113 | 114 | É possível converter os seguintes objetos em **Python** para **JSON**, e eles receberão um valor de equivalência em JSON como mostra a seguinte tabela: 115 | 116 | | Python | JSON | 117 | |--------|--------| 118 | | dict | Object | 119 | | list | Array | 120 | | tuple | Array | 121 | | str | String | 122 | | int | Number | 123 | | float | Number | 124 | | True | true | 125 | | False | false | 126 | | None | null | 127 | 128 | ## Exemplo com todos os Tipos de Dados 129 | 130 | Para compreendermos melhor o funcionamento da biblioteca json, vamos agora trabalhar em um exemplo contendo todos os tipos possíveis de dados. 131 | 132 | ```python 133 | import json 134 | 135 | personagem = { 136 | "nome": "Talantyr", 137 | "epiteto": "O Glorioso", 138 | "nível": 45, 139 | "vivo": True, 140 | "atributos": {"força": 45, "destreza": 60, "inteligência": 70}, 141 | "mascotes": ("Lobo","Coruja"), 142 | "magias": None, 143 | "itens": [ 144 | {"nome": "poção de mana", "quantidade": 5}, 145 | {"nome": "poção de vida", "quantidade": 7} 146 | ] 147 | } 148 | 149 | print(json.dumps(personagem, ensure_ascii=False)) 150 | # {"nome": "Talantyr", "epiteto": "O Glorioso", "nível": 45, "vivo": true, "atributos": {"força": 45, "destreza": 60, "inteligência": 70}, "mascotes": ["Lobo", "Coruja"], "magias": null, "itens": [{"nome": "poção de mana", "quantidade": 5}, {"nome": "poção de vida", "quantidade": 7}]} 151 | ``` 152 | 153 | Para obtermos um output mais limpo, podemos setar o atributo **indent** com um determinado número, neste caso específico, **4**: 154 | 155 | ```python 156 | print(json.dumps(personagem, ensure_ascii=False, indent=4)) 157 | ``` 158 | 159 | Dessa vez, temos o resultado que esperamos: 160 | 161 | ```javascript 162 | { 163 | "nome": "Talantyr", 164 | "epiteto": "O Glorioso", 165 | "nível": 45, 166 | "vivo": true, 167 | "atributos": { 168 | "força": 45, 169 | "destreza": 60, 170 | "inteligência": 70 171 | }, 172 | "mascotes": [ 173 | "Lobo", 174 | "Coruja" 175 | ], 176 | "magias": null, 177 | "itens": [ 178 | { 179 | "nome": "poção de mana", 180 | "quantidade": 5 181 | }, 182 | { 183 | "nome": "poção de vida", 184 | "quantidade": 7 185 | } 186 | ] 187 | } 188 | ``` 189 | 190 | Caso queiramos os atributos do resultado ordenados, podemos usar o parâmetro **sort_keys** como `True`: 191 | 192 | ```python 193 | print(json.dumps(p, indent=4, sort_keys=True)) 194 | ``` 195 | 196 | Dessa vez, temos o seguinte resultado: 197 | 198 | ```javascript 199 | { 200 | "atributos": { 201 | "destreza": 60, 202 | "força": 45, 203 | "inteligência": 70 204 | }, 205 | "epiteto": "O Glorioso", 206 | "itens": [ 207 | { 208 | "nome": "poção de mana", 209 | "quantidade": 5 210 | }, 211 | { 212 | "nome": "poção de vida", 213 | "quantidade": 7 214 | } 215 | ], 216 | "magias": null, 217 | "mascotes": [ 218 | "Lobo", 219 | "Coruja" 220 | ], 221 | "nome": "Talantyr", 222 | "nível": 45, 223 | "vivo": true 224 | } 225 | ``` 226 | 227 | Se quisermos, podemos facilmente converter o dicionário personagem em JSON (como já vimos anteriormente) e em seguida, salvar os dados em um arquivo de nome `personagem.json`: 228 | 229 | ```python 230 | dados_json = json.dumps(personagem, ensure_ascii=False, indent=4) 231 | 232 | with open('personagem.json','w') as json_file: 233 | json_file.write(dados_json) 234 | ``` 235 | 236 | Como podemos observar, os dados agora persistem no arquivo [personagem.json](https://github.com/the-akira/Python-Iluminado/blob/master/Arquivos/personagem.json) 237 | 238 | ## Utilizando uma API 239 | 240 | Vamos consumir uma simples [API](https://en.wikipedia.org/wiki/Representational_state_transfer) de testes para entendermos melhor a interação com outras aplicações que expõem seus serviços online. 241 | 242 | ```python 243 | import json 244 | import requests 245 | 246 | r = requests.get('https://jsonplaceholder.typicode.com/posts') 247 | posts = r.json() 248 | 249 | for post in posts: 250 | print(post) # Imprime todos os posts 251 | print(post['id']) # Imprime todos os ids 252 | print(post['title']) # Imprime todos os títulos 253 | print(post['body']) # Imprime todos os textos 254 | ``` 255 | 256 | Como podemos observar, conseguimos obter os dados com sucesso e agora podemos trabalhar com eles da forma que desejarmos. 257 | 258 | Experimente esta ideia trabalhando com outras API's, por exemplo a do [GitHub](https://api.github.com/). 259 | 260 | ## JSONPickle 261 | 262 | A biblioteca **[jsonpickle](https://jsonpickle.github.io/)** nos permite **serializar** e **deserializar** objetos complexos em Python para JSON e também de JSON. 263 | 264 | Para podermos usar suas funcionalidades, precisamos instalar ela com um simples comando: 265 | 266 | ``` 267 | pip install jsonpickle 268 | ``` 269 | 270 | Vejamos exemplos dela para ilustrar o seu uso. 271 | 272 | Vamos começar criando um objeto `Gato`: 273 | 274 | ```python 275 | class Gato: 276 | def __init__(self, nome, raca): 277 | self.nome = nome 278 | self.raca = raca 279 | ``` 280 | 281 | Agora vamos criar um novo `Gato` 282 | 283 | ```python 284 | gato = Gato('Osíris','Sphynx') 285 | ``` 286 | 287 | Transformando o objeto `Gato` em uma string JSON e salvando em um arquivo: 288 | 289 | ```python 290 | import jsonpickle 291 | 292 | jsonpickle.set_preferred_backend('json') 293 | jsonpickle.set_encoder_options('json', ensure_ascii=False) 294 | 295 | with open('gato.json', 'w') as file: 296 | frozen = jsonpickle.encode(gato) 297 | file.write(frozen) 298 | ``` 299 | 300 | Nosso objeto agora persiste no arquivo [gato.json](https://github.com/the-akira/Python-Iluminado/blob/master/Arquivos/gato.json) 301 | 302 | Lendo o arquivo JSON e decodificando para recriar o objeto `Gato`: 303 | 304 | ```python 305 | with open('gato.json', 'r') as file: 306 | contents = file.read() 307 | unfrozen = jsonpickle.decode(contents) 308 | print(unfrozen) # <__main__.Gato object at 0x7efdfeeca5c0> 309 | print(unfrozen.raca) # Sphynx 310 | print(unfrozen.nome) # Osíris 311 | ``` 312 | 313 | Essa breve introdução nos mostrou a importância do **JSON** atualmente e a capacidade que o Python tem de manipulá-lo com uma certa facilidade, inclusive. 314 | 315 | Se você deseja obter mais detalhes sobre a biblioteca padrão json em Python, visite **[docs.python](https://docs.python.org/3/library/json.html)**. Bons estudos! 316 | -------------------------------------------------------------------------------- /content/decoradores.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Decoradores' 3 | description: 'Aprenda sobre Decoradores' 4 | --- 5 | 6 | **Decoradores** são um elemento significante do Python, também são conhecidos como **[meta-programação](https://en.wikipedia.org/wiki/Metaprogramming)**, para simplificarmos sua ideia, podemos dizer que eles são funções que modificam a funcionalidade de uma outra função, eles nos ajudam a deixar o código menor e mais **Pythônico** (legível ao modo Python). O conceito de decoradores pode ser inicialmente um pouco difícil de capturarmos, mas vamos por partes. 7 | 8 | Antes de compreendermos os decoradores, é interessante que entendamos como as funções funcionam. Lembre que uma função retorna um valor baseado nos argumentos fornecidos a ela. Vejamos um simples exemplo: 9 | 10 | ```python 11 | def saudar(nome='Gabriel'): 12 | return f'Saudações, {nome}!' 13 | ``` 14 | 15 | Podemos agora chamar essa função sem um argumento (pois já existe um argumento padrão nela), ou com um argumento: 16 | 17 | ```python 18 | saudar() # 'Saudações, Gabriel!' 19 | saudar('Rafael') # 'Saudações, Rafael!' 20 | ``` 21 | 22 | Em geral, as funções em Python também podem ter efeitos colaterais, em vez de apenas transformar um *input* em um *output*. A função **print()** é um exemplo básico disso: ela retorna `None` enquanto tem o efeito colateral de enviar algo para o console. Porém, para entender os decoradores, basta pensar nas funções como algo que transforma determinados argumentos em um valor. 23 | 24 | Também podemos atribuir uma função a uma variável, para isso, não usamos parenteses, dessa maneira estamos guardando apenas a referência ao objeto função. 25 | 26 | ```python 27 | saudacao = saudar 28 | print(saudacao) # 29 | saudacao('Miguel') # 'Saudações, Miguel!' 30 | ``` 31 | 32 | Podemos por exemplo deletar a referência em memória da antiga função: 33 | 34 | ```python 35 | del saudar 36 | saudar() # NameError: name 'saudar' is not defined 37 | ``` 38 | 39 | Veja que se tentarmos invocá-la írá ocorrer um `NameError`, mas veja que ainda podemos chamar a outra referência que temos: 40 | 41 | ```python 42 | saudacao() # 'Saudações, Gabriel!' 43 | ``` 44 | 45 | Veja que mesmo deletando a função antiga, ainda conseguimos executar a função **saudacao()**! 46 | 47 | ## Funções dentro de Funções 48 | 49 | Em Python, funções são [first-class objects](https://stackoverflow.com/questions/245192/what-are-first-class-objects#:~:text=A%20first%20class%20object%20is,being%20storable%20in%20variables). Isso significa que as funções podem ser transmitidas e usadas como argumentos, assim como qualquer outro objeto (string, int, float, listas e assim por diante). 50 | 51 | Vamos começar definindo uma simples função: 52 | 53 | ```python 54 | def func(string): 55 | def wrapper(): 56 | print("Iniciada") 57 | print(string) 58 | print("Finalizada") 59 | return wrapper() 60 | ``` 61 | 62 | Observe que temos uma função de nome **func()** que recebe uma string como argumento e dentro dela temos uma função de nome **wrapper()** que não recebe nenhum argumento e imprime `"Iniciada"`, a **string** passada para a função **func()** e `"Finalizada"` e finalmente retorna a função **wrapper()** (ela mesma) invocando-a. Podemos usá-la da seguinte forma: 63 | 64 | ```python 65 | f = func("Hello World") 66 | # Iniciada 67 | # Hello World 68 | # Finalizada 69 | ``` 70 | 71 | Vamos agora modificá-la para que a função **wrapper()** não retorne a ela mesmo invocando-a, mas dessa vez apenas o objeto função. 72 | 73 | ```python 74 | def func(string): 75 | def wrapper(): 76 | print("Iniciada") 77 | print(string) 78 | print("Finalizada") 79 | return wrapper 80 | ``` 81 | 82 | Dessa vez para usá-la temos de usar o seguinte procedimento: 83 | 84 | ```python 85 | f = func("Hello World") 86 | print(f) # .wrapper at 0x7f7ab6fca0e0> 87 | f() 88 | # Iniciada 89 | # Hello World 90 | # Finalizada 91 | ``` 92 | 93 | Também existe a opção de chamá-la da seguinte forma: 94 | 95 | ```python 96 | func("Hello World")() 97 | # Iniciada 98 | # Hello World 99 | # Finalizada 100 | ``` 101 | 102 | Até então tudo bem, nada que venha a nos surpreender. Mas e se desejarmos passar uma outra função como argumento para **func()**? Vamos definir duas novas funções para testarmos: 103 | 104 | ```python 105 | def func(f): 106 | def wrapper(): 107 | print("Iniciada") 108 | f() 109 | print("Finalizada") 110 | return wrapper 111 | 112 | def f1(): 113 | print("Função f1() chamada!") 114 | 115 | def f2(): 116 | print("Função f2() chamada") 117 | ``` 118 | 119 | Observe que modificamos a função **wrapper()** e agora ela está invocando a função **f()** (esta que passaremos como argumento). Vamos agora chamar a função **func()** passando as funções **f1()** e **f2()** como argumento: 120 | 121 | ```python 122 | f1 = func(f1) 123 | f2 = func(f2) 124 | print(f1) # .wrapper at 0x7f7ab702ab90> 125 | print(f2) # .wrapper at 0x7f7ab702a950> 126 | f1() 127 | # Iniciada 128 | # Função f1() chamada! 129 | # Finalizada 130 | f2() 131 | # Iniciada 132 | # Função f2() chamada 133 | # Finalizada 134 | ``` 135 | 136 | Basicamente este é o conceito de decoradores, estamos usando a função **func()** para alterar o comportamento das funções **f1()** e **f2()**, porém existe uma maneira mais interessante de definí-los, em outras palavras, mais Pythônica. 137 | 138 | ## Decorando Funções 139 | 140 | Vamos decorar as funções **f1()** e **f2()** usando a sintaxe `@`: 141 | 142 | ```python 143 | @func 144 | def f1(): 145 | print("Função f1() chamada!") 146 | 147 | @func 148 | def f2(): 149 | print("Função f2() chamada") 150 | ``` 151 | 152 | Dessa vez podemos chamá-las diretamente e teremos o mesmo efeito anterior: 153 | 154 | ```python 155 | f1() 156 | # Iniciada 157 | # Função f1() chamada! 158 | # Finalizada 159 | f2() 160 | # Iniciada 161 | # Função f2() chamada 162 | # Finalizada 163 | ``` 164 | 165 | Faremos agora outra modificação, dessa vez as funções **wrapper()** e **f1()** passam a receber um argumento e a função passada como argumento para **func()** passa a ser invocada com esse argumento: 166 | 167 | ```python 168 | def func(f): 169 | def wrapper(x): 170 | print("Iniciada") 171 | f(x) 172 | print("Finalizada") 173 | return wrapper 174 | 175 | @func 176 | def f1(x): 177 | print(f"O valor de x é = {x}") 178 | 179 | @func 180 | def f2(): 181 | print("Função f2() chamada") 182 | ``` 183 | 184 | Vejamos agora o que ocorre se invocarmos as funções **f1()** e **f2()**: 185 | 186 | ```python 187 | f1(7) 188 | # Iniciada 189 | # O valor de x é = 7 190 | # Finalizada 191 | f2() # TypeError: wrapper() missing 1 required positional argument: 'x' 192 | ``` 193 | 194 | **f1()** é chamada e nos imprime o valor como esperado, porém **f2()** "quebra", não somo capazes de chamá-la, pois a função **wrapper()** espera um argumento. Para solucionar este problema podemos usar o conceito de `*args` e `**kwargs`, vamos então masi uma vez modificar nossas funções: 195 | 196 | ```python 197 | def func(f): 198 | def wrapper(*args, **kwargs): 199 | print("Iniciada") 200 | f(*args, **kwargs) 201 | print("Finalizada") 202 | return wrapper 203 | 204 | @func 205 | def f1(x): 206 | print(f"O valor de x é = {x}") 207 | 208 | @func 209 | def f2(): 210 | print("Função f2() chamada") 211 | 212 | f1(7) 213 | # Iniciada 214 | # O valor de x é = 7 215 | # Finalizada 216 | f2() 217 | # Iniciada 218 | # Função f2() chamada 219 | # Finalizada 220 | ``` 221 | 222 | Para finalizarmos, vamos modificar nossas funções **wrapper()** e **f1()** para retornar um valor: 223 | 224 | ```python 225 | def func(f): 226 | def wrapper(*args, **kwargs): 227 | print("Iniciada") 228 | valor_retorno = f(*args, **kwargs) 229 | print("Finalizada") 230 | return valor_retorno 231 | return wrapper 232 | 233 | @func 234 | def f1(x, y): 235 | print(f"O valor de x é = {x}") 236 | print(f"O valor de y é = {y}") 237 | return y + x 238 | 239 | f1 = f1(5,33) 240 | # Iniciada 241 | # O valor de x é = 5 242 | # O valor de y é = 33 243 | # Finalizada 244 | print(f1) # 38 245 | ``` 246 | 247 | ## Outros Exemplos 248 | 249 | Funções e métodos são chamados **callable** se for possível chamá-los. De fato, qualquer objeto que implemente o método especial `__call__()` é um **callable**, então um decorador seria um callable que retorna um callable. 250 | 251 | Então como já tinhamos dito na nossa introdução, um decorador recebe um função, adiciona alguma funcionalidade a ela e a retorna: 252 | 253 | ```python 254 | def embelezar(func): 255 | def interno(): 256 | print("Fui decorado") 257 | func() 258 | return interno 259 | 260 | def normal(): 261 | print("Eu sou normal") 262 | 263 | normal() # Eu sou normal 264 | bonito = embelezar(normal) 265 | bonito() 266 | # Fui decorado 267 | # Eu sou normal 268 | ``` 269 | 270 | Veja que a função **normal()** foi decorada e demos o nome à função retornada, que se chamou bonito. Uma forma mais eficaz de usarmos os decoradores é usando o símbolo `@` junto do nome da função decoradora e colocar ele em cima da definição da função a ser decorada. Por exemplo: 271 | 272 | ```python 273 | @embelezar 274 | def normal(): 275 | print("Eu sou normal também") 276 | 277 | normal() 278 | # Fui decorado 279 | # Eu sou normal também 280 | ``` 281 | 282 | ### Decorando Funções com Parâmetros 283 | 284 | O último **decorador** que escrevemos foi bastante simples, só funcionava com funções sem parâmatros, apenas para ilustrarmos o conceito, mas e se tivermos funções que operam com parâmetros? 285 | 286 | ```python 287 | def divisao(x, y): 288 | return x / y 289 | ``` 290 | 291 | A função recebe dois parâmetros **x** e **y**, sabemos que se passarmos **0** para **y** ocorrerá um erro. 292 | 293 | ```python 294 | print(divisao(10,2)) # 5.0 295 | print(divisao(3,0)) # ZeroDivisionError: division by zero 296 | ``` 297 | 298 | Agora vamos fazer um decorador para resolvermos esse problema. 299 | 300 | ```python 301 | def divisao_inteligente(func): 302 | def interior(x,y): 303 | print("Será feita uma divisão de {0} por {1}".format(x,y)) 304 | if y == 0: 305 | print("Impossível dividir") 306 | return 307 | return func(x,y) 308 | return interior 309 | 310 | @divisao_inteligente 311 | def divisao(x,y): 312 | return x / y 313 | 314 | divisao(3,3) 315 | # Será feita uma divisão de 3 por 3 316 | # 1.0 317 | divisao(3,0) 318 | # Será feita uma divisão de 3 por 0 319 | # Impossível dividir 320 | ``` 321 | 322 | ### Medindo Desempenho 323 | 324 | Podemos criar um decorar que é capaz de medir quanto tempo uma função leva para rodar: 325 | 326 | ```python 327 | import time 328 | 329 | def timer(func): 330 | def wrapper(*args, **kwargs): 331 | inicio = time.time() 332 | valor_retorno = func() 333 | total = time.time() - inicio 334 | print(f"Tempo: {total}") 335 | return valor_retorno 336 | return wrapper 337 | ``` 338 | 339 | Vamos definir duas funções para medí-las: 340 | 341 | ```python 342 | @timer 343 | def t1(): 344 | for _ in range(10_000_000): 345 | pass 346 | 347 | @timer 348 | def t2(): 349 | time.sleep(2.3) 350 | ``` 351 | 352 | Finalmente, vamos obter o tempo de cada uma: 353 | 354 | ```python 355 | t1() # Tempo: 0.36320018768310547 356 | t2() # Tempo: 2.302194118499756 357 | ``` 358 | 359 | Com esse estudo podemos considerar que decoradores são de certa forma um pouco complexos, mas que nos trazem novas possibilidades de trabalharmos em cima das funções, modificando seu comportamento. Eles são muito comuns também em **frameworks web**, como **[Flask](https://flask.palletsprojects.com/)** e **[Bottle](https://bottlepy.org/docs/dev/)** por exemplo. 360 | -------------------------------------------------------------------------------- /content/ambientes-virtuais.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Gerenciadores de Pacotes e Ambientes Virtuais' 3 | description: 'Aprenda sobre Gerenciadores de Pacotes e Ambientes Virtuais' 4 | --- 5 | 6 | **PIP** é o gerenciador de pacotes do Python, também conhecidos como **bibliotecas**. 7 | 8 | É importante notar que o termo "pacote" neste contexto está sendo usado como sinônimo de distribuição (ou seja, um pacote de software a ser instalado), não para se referir ao tipo de pacote que você importa em seu código-fonte Python (ou seja, um contêiner de módulos). É comum na comunidade Python referir-se a uma distribuição usando o termo "pacote". O uso do termo "distribuição" geralmente não é preferido, porque pode ser facilmente confundido com uma distribuição Linux ou outra distribuição de software maior como o próprio Python. 9 | 10 | A partir da versão 3.4 do Python o PIP já vem incluído por padrão com a instalação do Python, então existem grandes chances de você já tê-lo em sua máquina. 11 | 12 | Para confirmar se ele está instalado, vamos digitar o seguinte comando na nossa **interface de linha de comando**: 13 | 14 | ``` 15 | pip --version 16 | ``` 17 | 18 | Caso ele não esteja presente em sua máquina, você pode encontrá-lo em: **https://pypi.org/project/pip/** ou **[get-pip.py](https://bootstrap.pypa.io/get-pip.py)**: 19 | 20 | - Faça o download do arquivo `get-pip.py` 21 | - Execute o comando `python get-pip.py`. Isso irá instalar ou atualizar o pip. 22 | 23 | Outra opção de instalação é executar o comando: 24 | 25 | ``` 26 | python -m ensurepip --default-pip 27 | ``` 28 | 29 | Para confirmar se o pip está atualizado, você pode executar o seguinte comando: 30 | 31 | ``` 32 | python -m pip install --upgrade pip 33 | ``` 34 | 35 | Para navegar através da lista de mais de `190,943` projetos, `2,069,359` arquivos e `354,989` usuários, visite: **https://pypi.org** 36 | 37 | ## Pacotes 38 | 39 | Um pacote seria um conjunto de arquivos para um módulo, como já vimos antes, módulos são como bibliotecas de código que podemos incluir em nossos projetos para usarmos suas funcionalidades e facilitar nossa vida como programadores. 40 | 41 | Normalmente, não armazenamos todos os nossos arquivos em nosso computador no mesmo local. Usamos uma hierarquia de diretórios bem organizada para facilitar o acesso e gerência. 42 | 43 | Conforme nosso programa cresce em tamanho com muitos módulos, colocamos módulos semelhantes em um pacote e módulos diferentes em pacotes diferentes. Isso torna um projeto (programa) fácil de gerenciar. 44 | 45 | Da mesma forma, como um diretório pode conter sub-diretórios e arquivos, um pacote Python pode ter sub-pacotes e módulos. 46 | 47 | Um diretório deve conter um arquivo denominado `__init__.py` para que o Python o considere como um pacote. Este arquivo pode ser deixado vazio, mas geralmente colocamos o código de inicialização para esse pacote neste arquivo. 48 | 49 | A seguinte ilustração nos apresenta a ideia de como funciona a estrutura de um projeto, usamos como exemplo um pacote de nome **Game** que possui diversos módulos. 50 | 51 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Package.png) 52 | 53 | ### Instalando Pacotes 54 | 55 | Novamente, vamos abrir nossa **interface de linha de comando** e vamos até o diretório que está nosso script. Digitaremos o seguinte comando para instalar a biblioteca [requests](https://requests.readthedocs.io/en/master/): 56 | 57 | ```python 58 | pip install requests 59 | ``` 60 | 61 | Será iniciado um processo de *download e instalação*, aguarde um pouco e estará pronto, agora poderemos usar a nova biblioteca. 62 | 63 | ### Utilizando o Pacote 64 | 65 | Uma vez que já temos requests instalada, para usarmos é só importá-la, assim como fazemos com os módulos padrão do Python: 66 | 67 | ```python 68 | import requests 69 | 70 | print(dir(requests)) 71 | # ['ConnectionError', 'FileModeWarning', 'HTTPError', 'NullHandler', 'PreparedRequest', 'Request', 'RequestException', 'Response', 'Session', 'Timeout', 'TooManyRedirects', 'URLRequired', '__author__', '__build__', '__builtins__', '__cached__', '__copyright__', '__doc__', '__file__', '__license__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__title__', '__version__', 'adapters', 'api', 'auth', 'certs', 'codes', 'compat', 'cookies', 'delete', 'exceptions', 'get', 'head', 'hooks', 'logging', 'models', 'options', 'packages', 'patch', 'post', 'put', 'request', 'session', 'sessions', 'status_codes', 'structures', 'utils', 'warnings'] 72 | 73 | r = requests.get("http://google.com") 74 | print(r.status_code) # 200, significa que a requisição ocorreu com sucesso 75 | print(r.text) # Retorna o conteúdo HTML da página 76 | print(r.encoding) # ISO-8859-1, codificação usada na página 77 | ``` 78 | 79 | Como podem ver, com um rápido download e instalação, temos acesso a uma poderosa biblioteca chamada **requests**, que nos permite fazer requisições **[HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)** e uma série de outras funcionalidades web. 80 | 81 | ### Removendo um Pacote 82 | 83 | Para desinstalarmos um pacote de nossa máquina podemos usar o comando `uninstall` 84 | 85 | ``` 86 | pip uninstall requests 87 | ``` 88 | 89 | É necessário confirmarmos a desinstalação com a tecla `y`. 90 | 91 | ### Listando os Pacotes 92 | 93 | Podemos usar o comando `list` para listarmos os pacotes que temos instalado em nossa máquina: 94 | 95 | ``` 96 | pip list 97 | ``` 98 | 99 | ### Atualizando um Pacote Existente 100 | 101 | O comando `install --upgrade` nos permite atualizar um pacote para sua versão mais recente: 102 | 103 | ``` 104 | pip install --upgrade requests 105 | ``` 106 | 107 | ### Obtendo Informações 108 | 109 | Através do comando `show` podemos obter informações sobre um determinado pacote: 110 | 111 | ``` 112 | pip show requests 113 | ``` 114 | 115 | Podemos também fazer pesquisas por **palavras-chave**: 116 | 117 | ``` 118 | pip search http 119 | ``` 120 | 121 | # Ambientes Virtuais 122 | 123 | O principal propósito dos **Ambientes Virtuais** é criar um ambiente isolado para projetos Python. Isso significa que cada projeto pode ter suas próprias dependências, independente da dependência de outros projetos. Eles são essenciais para evitarmos conflitos de versões de bibliotecas entre os nossos projetos. 124 | 125 | Python, como a maioria das outras linguagens de programação modernas, tem sua própria maneira única de baixar, armazenar e resolver pacotes. Embora isso tenha suas vantagens, algumas decisões interessantes foram tomadas sobre o armazenamento e a resolução de pacotes, o que levou a alguns problemas - especialmente em relação à como e onde os pacotes são armazenados. 126 | 127 | Existem alguns locais diferentes onde esses pacotes podem ser instalados em seu sistema. Por exemplo, a maioria dos pacotes de sistema são armazenados em um diretório filho, no qual o caminho fica armazenado em [sys.prefix](https://docs.python.org/3/library/sys.html#sys.prefix). 128 | 129 | Sendo assim, podemos usar a biblioteca **sys** para sabermos onde `sys.prefix` está apontando: 130 | 131 | ```python 132 | import sys 133 | print(sys.prefix) # /home/akira/anaconda3 134 | ``` 135 | 136 | Veja que no meu caso, estou usando anaconda e posso usar este caminho para saber quais pacotes eu tenho instalado com o seguinte comando Linux: 137 | 138 | ``` 139 | ls -la /home/akira/anaconda3/lib/python3.7/ 140 | ``` 141 | 142 | Mas afinal, por que essas informações são relevantes? 143 | 144 | É importante saber isso porque, por padrão, todos os projetos em seu sistema usarão esses mesmos diretórios para armazenar e recuperar pacotes de sites (bibliotecas de terceiros). Inicialmente, isso pode não parecer problemático, e não é realmente, para pacotes de sistema (pacotes que fazem parte da biblioteca Python padrão), mas importa para pacotes de terceiros. 145 | 146 | Considere o seguinte cenário em que você tem dois projetos: **ProjetoA** e **ProjetoB**, ambos os quais dependem da mesma biblioteca, **TimeLib**. O problema se torna aparente quando começamos a exigir versões diferentes do TimeLib. Talvez o ProjectA precise da v1.0.0, enquanto o ProjectB requer a v2.0.0 mais recente, por exemplo. 147 | 148 | Isso irá gerar conflitos e por este motivo os ambientes virtuais são tão importantes! 149 | 150 | Para saber mais detalhes sobre os **Ambientes Virtuais** você pode visitar: **[venv](https://docs.python.org/3/library/venv.html)** 151 | 152 | ## Usando Ambientes Virtuais 153 | 154 | Antes de tudo, devemos instalar a ferramenta `virtualenv` que nos permite trabalhar com ambientes virtuais. 155 | 156 | ``` 157 | pip install virtualenv 158 | ``` 159 | 160 | Lembrando que se você instalou a versão 3 do Python, é provável que você já o módulo `venv` da biblioteca padrão em seu computador. Agora que você já tem a ferramenta para criar **ambientes virtuais**, vamos criar um novo **diretório** em nossa máquina e navegar até ele através de nossa **interface de linha de comando** e digitar o seguinte comando 161 | 162 | ``` 163 | # Para Python 2 164 | virtualenv env 165 | 166 | # Para Python 3 167 | python3 -m venv env 168 | ``` 169 | 170 | O comando acima irá criar um diretório chamado `env` (nome arbitrário escolhido por nós) que contém uma estrutura similar a essa: 171 | 172 | ``` 173 | ├── bin 174 | │ ├── activate 175 | │ ├── activate.csh 176 | │ ├── activate.fish 177 | │ ├── easy_install 178 | │ ├── easy_install-3.5 179 | │ ├── pip 180 | │ ├── pip3 181 | │ ├── pip3.5 182 | │ ├── python -> python3.5 183 | │ ├── python3 -> python3.5 184 | │ └── python3.5 -> /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 185 | ├── include 186 | ├── lib 187 | │ └── python3.5 188 | │ └── site-packages 189 | └── pyvenv.cfg 190 | ``` 191 | 192 | Cada *folder* no diretório `env` contém: 193 | 194 | - **bin**: arquivos que interagem com o ambiente virtual 195 | - **include**: Cabeçalhos **C** que compilam os pacotes Python 196 | - **lib**: Uma cópia da versão Python juntamente com o *folder* `site-packages` onde cada dependência está localizada 197 | 198 | ## Ativando um Ambiente Virtual 199 | 200 | Dentro do *folder* **bin** que vimos anteriormente existem **scripts de ativação**, esses scripts são usados para setar nossa **[Shell](https://en.wikipedia.org/wiki/Shell_(computing))** para usar o executável Python do ambiente e os `site-packages`. 201 | 202 | De forma a usarmos os pacotes e recursos de um **ambiente virtual** é necessário que ativemos ele: 203 | 204 | ``` 205 | source env/bin/activate 206 | ``` 207 | 208 | Ou até mesmo utilizando somente `.` 209 | 210 | ``` 211 | . env/bin/activate 212 | ``` 213 | 214 | Perceba que ao ativarmos o ambiente virtual, nosso **prompt** de comandos irá se alterar para nos indicar que o ambiente está ligado. Caso você queira desativar o **ambiente virtual** basta digitar: 215 | 216 | ```python 217 | deactivate 218 | ``` 219 | 220 | Agora que vimos como **ativar** e **desativar** nosso ambiente virtual, vamos reativá-lo e testá-lo instalando a biblioteca [bcrypt](https://pypi.org/project/bcrypt): 221 | 222 | ```python 223 | pip install bcrypt 224 | ``` 225 | 226 | Abra agora o **Python Interactivo** ou um **Script** e vamos testar se a biblioteca está instalada corretamenta: 227 | 228 | ```python 229 | import bcrypt 230 | 231 | bcrypt.hashpw('senha'.encode('utf-8'), bcrypt.gensalt(12)) 232 | # b'$2b$12$ZT52zrACwPVFy1ST8UbsKuRQ/LZmhMvmMB7EqchU1VUQTLTi4X7Mu' 233 | ``` 234 | 235 | ## Gerando o Arquivo requirements.txt 236 | 237 | O comando `pip freeze` nos permite listar os pacotes que estão instalados em nossa **máquina** ou, caso estejamos em um **ambiente virtual**, os pacotes que nele estão presentes. 238 | 239 | É muito comum existir em projetos o arquivo `requirements.txt` que mostra os pacotes e suas versões necessárias para que o projeto possa funcionar corretamente, também é possível instalar pacotes através do arquivo `requirements.txt` 240 | 241 | Assumindo que estamos em nosso **ambiente virtual** e temos a biblioteca **bcrypt** instalada, vamos executar: 242 | 243 | ```python 244 | pip freeze > requirements.txt 245 | ``` 246 | 247 | Ao verificar o contéudo do arquivo **requirements.txt**, encontramos o seguinte: 248 | 249 | ``` 250 | bcrypt==3.1.7 251 | cffi==1.12.3 252 | pycparser==2.19 253 | six==1.12.0 254 | ``` 255 | 256 | Caso queiramos instalar todos os pacotes contidos nele podemos usar o comando: 257 | 258 | ```python 259 | pip install -r requirements.txt 260 | ``` 261 | 262 | ## Outras Alternativas 263 | 264 | Pip é uma ferramenta essencial para todos os Pythonistas e é usada por muitos aplicativos e projetos para gerenciamento de pacotes, ainda sim, existem outras alternativas muito boas que podemos usar em nossos projetos. 265 | 266 | ### Conda 267 | 268 | Conda é um gerenciador de pacotes, dependências e ambientes para muitas linguagens, incluindo Python. Na verdade, sua origem vem do [Anaconda](https://www.anaconda.com/), que começou como um pacote de ciência de dados para Python. 269 | 270 | O Conda é amplamente utilizado para aplicativos de ciência de dados e *Machine Learning*, e usa seu próprio índice para hospedar pacotes compatíveis. 271 | 272 | Conda não apenas permite que você gerencie dependências de pacote, mas também gerencia ambientes virtuais para seus aplicativos, instala distribuições Python compatíveis e empacota seu aplicativo para implantação na produção. 273 | 274 | Além do **pip** e do **ambiente virtual** tradicional que utilizamos anteriormente, também existem outras opções de gerenciadores de pacotes para Python. 275 | 276 | Você pode obter mais detalhes sobre Conda em: https://docs.conda.io/en/latest/ 277 | 278 | ### Pipenv 279 | 280 | Pipenv é uma ferramenta que visa trazer o melhor de todos os mundos de pacotes (bundler, composer, npm, cargo, yarn, etc.) para o mundo Python. O Windows é um cidadão de primeira classe no Pipenv. 281 | 282 | Ele cria e gerencia automaticamente um virtualenv para seus projetos, bem como adiciona / remove pacotes de seu Pipfile conforme você instala / desinstala pacotes. Ele também gera o sempre importante `Pipfile.lock`, que é usado para produzir compilações determinísticas. 283 | 284 | Você pode obter mais detalhes sobre ele em: https://pipenv.pypa.io/en/latest/ 285 | -------------------------------------------------------------------------------- /content/introducao.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Introdução' 3 | description: 'Capítulo Introdutório' 4 | --- 5 | 6 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Introduction.png) 7 | 8 | Python é uma linguagem de programação **[interpretada](https://pt.wikipedia.org/wiki/Linguagem_interpretada)**, **[de alto nível](https://pt.wikipedia.org/wiki/Linguagem_de_programação_de_alto_nível)**, que pode ser aplicada em diversas soluções. Famosa por sua sintaxe amigável, ela vem ganhando uma expressiva popularidade nos últimos anos. Foi criada por Guido Van Rossum no 9 | período de 1985-1990, seu código fonte está disponível sob o **GNU General Public License (GPL)**. Python conta com uma **[tipagem dinâmica](https://pt.wikipedia.org/wiki/Sistema_de_tipos)** e um sistema de gerenciamento de memória automático, sendo capaz de suportar múltiplos **[paradigmas de programação](https://pt.wikipedia.org/wiki/Paradigma_de_programação)**. 10 | 11 | Python é uma linguagem poderosa e de fácil aprendizado. Possui **[estruturas de dados](https://pt.wikipedia.org/wiki/Estrutura_de_dados)** eficientes e de alto nível e uma simples e efetiva abordagem em relação à **[programação orientada a objetos](https://pt.wikipedia.org/wiki/Programação_orientada_a_objetos)**. A sintaxe elegante de Python e sua **tipagem dinâmica**, juntamente com sua natureza interpretada, faz do Python uma linguagem ideal para *scripting* e desenvolvimento rápido de aplicações em muitas áreas e para diversas plataformas. 12 | 13 | O **interpretador** Python e a extensiva **[standard library](https://docs.python.org/3/library/)** estão disponíveis gratuitamente na forma *source* ou *binary* para todas as maiores plataformas através do **[site oficial Python](https://www.python.org/)**. 14 | 15 | ## As principais aplicações de Python são: 16 | 17 | - Desenvolvimento web **[(lado do servidor)](https://pt.wikipedia.org/wiki/Server-side)** 18 | - Desenvolvimento de softwares em geral 19 | - Matemática e Computação Científica 20 | - Inteligência Artificial, **[Machine Learning](https://en.wikipedia.org/wiki/Machine_learning)**, **[Deep Learning](https://en.wikipedia.org/wiki/Deep_learning)** 21 | - **[Scripting](https://pt.wikipedia.org/wiki/Linguagem_de_script)** e automação de tarefas repetitivas 22 | - Testes de software 23 | 24 | ## Por que aprender Python? 25 | 26 | - Python é capaz de rodar em múltiplas plataformas (**Windows**, **Linux**, **MacOS**, **Raspberry Pi**, etc) 27 | - Python suporta **programação interativa** (Interação direta com o interpretador) 28 | - Sua sintaxe é simples de compreender 29 | - Suporta múltiplos **[paradigmas de programação](https://pt.wikipedia.org/wiki/Paradigma_de_programação)** 30 | - Python pode ser usada para prototipação rápida 31 | - Python está apta a se conectar com sistemas de **[banco de dados](https://pt.wikipedia.org/wiki/Banco_de_dados)**, pode também ler e modificar arquivos 32 | - Pode ser utilizada para lidar com grandes quantidades de dados e executar cálculos matemáticos complexos 33 | - Python conta com uma comunidade gigantesca e muito material de aprendizado! 34 | 35 | ## Importante 36 | 37 | - A versão mais recente de Python é o Python 3, no qual iremos utilizar nesse guia, porém a versão Python 2 ainda é muito popular, embora não esteja mais recebendo suporte da **Python Software Foundation** 38 | - Python pode ser integrada com **C**, **C++**, **CORBA**, **Java**. Caso haja a necessidade de trabalhar com códigos de alta perfomance 39 | - Atualmente muitas das grandes corporações utilizam Python, podemos citar elas: **Google**, **Facebook**, **Microsoft**, **NASA**, **CERN**. 40 | 41 | # Computação 42 | 43 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/BinaryNumbers.gif) 44 | 45 | Antes de iniciarmos nossos estudos sobre a linguagem Python, é importante que tenhamos uma breve Introdução à Computação. 46 | 47 | A Computação é qualquer tipo de cálculo que inclui etapas aritméticas e não-aritméticas e que segue um modelo bem definido (por exemplo, um [algoritmo](https://en.wikipedia.org/wiki/Algorithm)). 48 | 49 | Dispositivos mecânicos ou eletrônicos (ou, historicamente, pessoas) que realizam cálculos são conhecidos como computadores. Uma disciplina especialmente conhecida do estudo da computação é a [ciência da computação](https://en.wikipedia.org/wiki/Computer_science). 50 | 51 | A Computação pode ser vista como um fenômeno puramente físico que ocorre dentro de um [sistema físico](https://en.wikipedia.org/wiki/Physical_system) fechado chamado computador. Exemplos de tais sistemas físicos incluem computadores digitais, computadores mecânicos, computadores quânticos, computadores de DNA, computadores moleculares ou até mesmo computadores analógicos. Esse ponto de vista foi adotado pela [física da computação](https://en.wikipedia.org/wiki/Physics_of_computation), um ramo da física teórica, bem como pelo campo da [computação natural](https://en.wikipedia.org/wiki/Natural_computing). 52 | 53 | Um ponto de vista ainda mais radical, o [pancomputacionalismo](https://en.wikipedia.org/wiki/Pancomputationalism), é o postulado da [física digital](https://en.wikipedia.org/wiki/Digital_physics) que argumenta que a evolução do universo é em si uma computação. 54 | 55 | ## Computação na Prática 56 | 57 | Programação de computador é o processo de escrever instruções que são executadas por computadores. As instruções, também conhecidas como código, são escritas em uma linguagem de programação que o computador pode entender e usar para realizar uma tarefa ou resolver um problema. 58 | 59 | Para que possamos escrever programas de qualidade e eficientes, é importante que conheçamos conceitos como: 60 | 61 | - Representação de conhecimento através de **Estruturas de Dados** 62 | - **Iteração** e **Recursão** como metáforas computacionais 63 | - **Abstração** de procedimentos e tipos de dados 64 | - **Organizar** e **Modularizar** sistemas utilizando objetos [classes](https://docs.python.org/3/tutorial/classes.html) e métodos 65 | - Diferentes classes de **algoritmos** ([searching](https://en.wikipedia.org/wiki/Search_algorithm), [sorting](https://en.wikipedia.org/wiki/Sorting_algorithm)) 66 | - **Complexidade** de algoritmos 67 | 68 | ## O que um Computador faz? 69 | 70 | Fundamentalmente ele é capaz de realizar cálculos (bilhões de cálculos por segundo) e também é capaz de lembrar resultados (centenas de gigabytes de storage). 71 | 72 | Quais tipos de cálculos ele pode executar? Um computador pode executar cálculos que são **pré-construídos** na linguagem e também aqueles que você define como programador. É importante lembrarmos que **Computadores** apenas sabem o que dizemos a eles, então é importante que forneçamos as instruções corretas para que possamos obter os resultados desejados. 73 | 74 | ## Tipos de Conhecimento 75 | 76 | Em [epistemologia](https://en.wikipedia.org/wiki/Epistemology), conhecimento descritivo, também conhecido como **Conhecimento Declarativo** é uma afirmação de um fato, em outras palavras, é o conhecimento que pode ser expresso em uma frase declarativa ou uma proposição indicativa (por exemplo: "Está chovendo lá fora"). 77 | 78 | Conhecimento processual, também conhecido como **Conhecimento Imperativo** é uma **receita** ou "tutorial", é o conhecimento exercido no desempenho de alguma tarefa. 79 | 80 | Podemos considerar um algoritmo, por exemplo: 81 | 82 | - Ler um número 83 | - Verificar se ele é maior que **0** 84 | - Se o número for maior que **0**, retornar que ele é **positivo** 85 | - Verificar se ele é menor que **0** 86 | - Se o número for menor que **0**, retornar que ele é **negativo** 87 | - Se nenhum dos casos acima for atendido, então ele é **0**. 88 | - Fim do algoritmo 89 | 90 | O fluxograma a seguir nos apresenta esta ideia visualmente: 91 | 92 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Algorithm.png) 93 | 94 | ## Calculando a Raiz Quadrada 95 | 96 | Na matemática, a raiz quadrada de um número **x** é um número **y** tal que `y² = x`. Em outras palavras, um número **y** cujo quadrado (o resultado da multiplicação do número por ele mesmo, ou `y*y`) é x. 97 | 98 | Vamos então definir que: 99 | 100 | - A raiz quadrada de um número **x** é **y** de forma que `y*y = x` 101 | 102 | - A receita para deduzir a raiz quadrada de um número **x** é: 103 | 104 | 1. Começar com uma suposição **g** 105 | 2. Se `g*g` é próximo o suficiente de **x**, pare e diga que **g** é a resposta 106 | 3. Caso contrário faça uma nova suposição calculando a média de **g** e **x/g** 107 | 4. Utilizando a nova suposição, repita o processo até se aproximar 108 | 109 | Neste exemplo, queremos obter a raiz quadrada do número **16**, que é **4**, veja que através do nosso algoritmo somos capazes de alcançar um número muito próximo de **4**. 110 | 111 | | `g` | `g*g` | `x/g` |`(g+x/g)/2`| 112 | |--------|---------|-------|-----------| 113 | | 3 | 9 | 16/3 | 4.17 | 114 | | 4.17 | 17.36 | 3.837 | 4.0035 | 115 | | **4.0035** | 16.0277 | 3.997 | 4.000002 | 116 | 117 | ## O que é uma Receita? 118 | 119 | Uma receita é um conjunto de instruções que descreve como preparar ou fazer algo, em outras palavras: 120 | 121 | - Uma sequência de simples passos 122 | - Processo de **Controle de Fluxo** que específica quando cada passo é executado 123 | - Um meio de determinar quando parar 124 | 125 | 1+5+7 = UM **ALGORITMO**! 126 | 127 | ## Computadores são Máquinas 128 | 129 | Um computador é uma máquina que pode ser instruída a realizar sequências de operações aritméticas ou lógicas automaticamente por meio de programação de computador. Os computadores modernos têm a capacidade de seguir conjuntos generalizados de operações, chamados programas. 130 | 131 | Existem diversos tipos de computadores, por exemplo: 132 | 133 | - Computador de **Programa Fixo**: Calculadora 134 | - Computador de **Programa Armazenado**: A máquina armazena e executa instruções 135 | 136 | ## Arquitetura Básica do Computador 137 | 138 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/ComputerArchitecture.png) 139 | 140 | ## Computador de Programa Armazenado 141 | 142 | Um computador de programa armazenado é aquele que armazena instruções do programa em uma memória acessível eletronicamente ou opticamente. Isso contrasta com os sistemas que armazenavam as instruções do programa com plugboards ou mecanismos semelhantes. 143 | 144 | A Sequência de Instruções são então armazenadas dentro do computador. Construídos através de um conjunto pré-definido de instruções primitivas: 145 | 146 | 1. Aritmética e Lógica 147 | 2. Testes simples 148 | 3. Movendo dados 149 | 150 | Um Programa Especial (Interpretador) **executa cada instrução em ordem** e pode ser usado em testes para alterar o fluxo de controle. 151 | 152 | ## Primitivos Básicos 153 | 154 | Na computação, primitivos de linguagem são os elementos mais simples disponíveis em uma linguagem de programação. Um primitivo é a menor 'unidade de processamento' disponível para um programador de uma determinada máquina, ou pode ser um elemento atômico de uma expressão em uma linguagem. 155 | 156 | Um primitivo é um tipo de dados fundamental que não pode ser dividido em um tipo de dados mais simples. Por exemplo, um **inteiro** é um tipo de dados primitivo, enquanto que um **array**, que pode armazenar vários tipos de dados, não é. 157 | 158 | - Turing mostrou que podemos **computar tudo** utilizando apenas 6 primitivos 159 | - Linguagens de programação modernas possuem conjuntos de primitivos mais convenientes 160 | - É possível abstrair métodos para criar **novos primitivos** 161 | - Qualquer cálculo computável em uma linguagem é computável em qualquer outra linguagem de programação 162 | 163 | ## Criando Receitas 164 | 165 | Uma linguagem de programação fornece um conjunto de **operações** primitivas. **Expressões** são complexas combinações legais de primitivos em uma linguagem de programação. Expressões e Computações possuem **valores** e **sentido** em uma linguagem de programação 166 | 167 | ## Aspectos das Linguagens 168 | 169 | As linguagens possuem **Constructos Primitivos**, em português, por exemplo, temos as **palavras**, nas linguagens de programação temos os **números**, **strings** e **operadores simples**. 170 | 171 | Elas também possuem uma **Sintaxe**, por exemplo, em português podemos construir a seguinte frase "gato caxorro garoto", que é inválida sintaticamente, também podemos construir "mãe abraça o garoto", que é válida sintaticamente. Nas linguagens de programação existem as mesmas situações, por exemplo `"oi"5` é uma definição inválida em termos de sintaxe, porém `3*5` é válido, pois define a multiplicação de dois números de maneira correta, veja que aqui estamos usando um exemplo geral e não estamos falando de uma linguagem específica. 172 | 173 | Além disso, as linguagens também possuem a **Semântica Estática**, no qual strings sintaticamente válidas possuem sentido, no português, por exemplo, podemos definir "Eu árvore fome", embora seja uma expressão valida sintaticamente, ela tem erro de semântica, pois não há sentido no que se quer dizer. Nas linguagens de programação temos o mesmo problema, se definirmos por exemplo `3+"oi"` teremos um erro semântico, pois esta soma não faz sentido. 174 | 175 | A **Semântica** é então o sentido associado com uma string de símbolos sintaticamente correta com nenhum erro de semântica. 176 | 177 | ## Quando Ocorrem Erros 178 | 179 | Erros são os problemas ou falhas no programa que fazem com que nosso programa se comporte de forma inesperada, existem diversos tipos de erros, podemos citar por exemplo: 180 | 181 | - Erros de Sintáxe: Comuns e fáceis de perceber 182 | - Erros de Semântica Estática: Algumas linguagens checam por eles antes de rodar o programa, eles podem causar comportamento imprevisível 183 | - Nenhum erro de Semântica, porém um sentido diferente do que o programador desejava expressar ocorre: Programa crasha, para de rodar, programa roda para sempre, programa dá uma resposta, porém diferente do esperado 184 | 185 | ## Programas em Python 186 | 187 | Um programa é uma sequência de definições e comandos, estas definições devem ser bem avaliadas. Também podemos considerar ele como comandos executados pelo Interpretador Python em uma shell, comandos (afirmações) instruem o interpretador a fazerem algo e podem ser digitados diretamente em uma shell ou guardados em um arquivo que é então lido na shell e avaliado. 188 | 189 | ## Objetos 190 | 191 | Python é uma linguagem de programação orientada a objetos. Quase tudo em Python é um objeto, com suas propriedades e métodos. 192 | 193 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Object.png) 194 | 195 | Devemos estar cientes da importância dos Objetos, pois programas manipulam **objetos de dados**. Objetos possuem um **tipo** que define os tipos de ações que os programas podem fazer com eles, por exemplo: 196 | 197 | - Gabriel é um humano, sendo assim ele pode caminhar, falar, etc. 198 | - Zeus é um cachorro, sendo assim ele pode latir, rosnar, etc. 199 | 200 | Objetos são normalmente divididos em duas categorias: 201 | 202 | - Escalares (não podem ser subdivididos) 203 | - Não-Escalares (possui uma estrutura interna que pode ser acessada) 204 | 205 | Agora que temos informações fundamentais básicas sobre princípios da computação e da linguagem **Python**, podemos iniciar a configuração de nosso Ambiente de Programação. 206 | -------------------------------------------------------------------------------- /content/expressoes-regulares.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Expressões Regulares' 3 | description: 'Aprenda sobre Expressões Regulares' 4 | --- 5 | 6 | **Expressões regulares** são um mecanismo muito poderoso para manipulação de **strings**, também conhecido como **regex** ou **regexp**, é um campo de estudo muito abrangente na **ciência da computação teórica** e **linguagens formais**. 7 | 8 | Pode-se dizer que é uma sequência de caracteres que define um padrão de busca, normalmente este padrão é usado por algoritmos de busca de strings, onde é feito uma busca por determinado padrão, seja para encontrá-lo ou até mesmo encontrá-lo e alterá-lo, também é muito usado para *validação de input de dados*. 9 | 10 | O conceito surgiu na década de 1950, quando o matemático americano [Stephen Cole Kleene](https://en.wikipedia.org/wiki/Stephen_Cole_Kleene) formalizou a descrição de uma [linguagem regular](https://en.wikipedia.org/wiki/Regular_language). O conceito entrou em uso comum com utilitários de processamento de texto do Unix. Diferentes sintaxes para escrever expressões regulares existem desde a década de 1980, sendo uma o padrão [POSIX](https://en.wikipedia.org/wiki/POSIX) e outra, amplamente utilizada, a sintaxe [Perl](https://en.wikipedia.org/wiki/Perl). 11 | 12 | Expressões regulares são usadas em [search engines](https://en.wikipedia.org/wiki/Search_engine), *search and replace dialogs* de processadores de texto e editores de texto, em utilitários de processamento de texto como [sed](https://en.wikipedia.org/wiki/Sed) e [AWK](https://en.wikipedia.org/wiki/AWK) e em análise lexical. Muitas linguagens de programação fornecem recursos de regex integrados ou por meio de bibliotecas, como é o caso da linguagem Python que nos oferece a biblioteca [re](https://docs.python.org/3/library/re.html). 13 | 14 | ## Introdução 15 | 16 | Uma expressão regular, geralmente chamada de padrão, especifica um conjunto de strings necessárias para um propósito específico. Uma maneira simples de especificar um conjunto finito de strings é listar seus elementos ou membros. No entanto, muitas vezes existem maneiras mais concisas, por exemplo, o conjunto contendo as três cadeias de caracteres "Handel", "Händel" e "Haendel" pode ser especificado pelo padrão `H(ä|ae?)Ndel`, dizemos que esse padrão corresponde a cada uma das três strings. Na maioria dos formalismos, se existe pelo menos uma expressão regular que corresponde a um determinado conjunto, então existe um número infinito de outras expressões regulares que também correspondem a ela - a especificação não é única. 17 | 18 | **Âncoras**: `^` e `$` 19 | 20 | | Exemplo | Descrição | URL | 21 | |----------|------------------------------------------------|------------------------------------| 22 | | ^Py | Encontra qualquer string que comece com Py | **https://regex101.com/r/cO8lqs/4303** | 23 | | on$ | Encontra uma string que termina com on | **https://regex101.com/r/cO8lqs/4304** | 24 | | ^Python$ | Encontra a string Python | **https://regex101.com/r/cO8lqs/4305** | 25 | | Python | Encontra qualquer string que tenha Python em si | **https://regex101.com/r/cO8lqs/23892** | 26 | 27 | **Quantificadores**: `*`, `+`, `?` e `{}` 28 | 29 | | Exemplo | Descrição | 30 | |------------|-------------------------------------------------------------------------------------| 31 | | abc* | Encontra uma string que tenha ab seguido por zero ou mais c | 32 | | abc+ | Encontra uma string que tenha ab seguido por um ou mais c | 33 | | abc? | Encontra uma string que tenha ab seguido por zero, ou um c | 34 | | abc{2} | Encontra uma string que tenha ab seguido por dois c | 35 | | abc{2,} | Encontra uma string que tenha ab seguido por dois ou mais c | 36 | | abc{2,5} | Encontra uma string que tenha ab seguido por 2 até no máximo 5 c | 37 | | a(bc)* | Encontra uma string que tenha a seguido por zero ou mais cópias da sequência bc | 38 | | a(bc){2,5} | Encontra uma string que tenha a seguido por 2 até no máximo 5 cópias da sequência bc | 39 | 40 | **Operador OU**: `|` e `[]` 41 | 42 | | Exemplo | Descrição | 43 | |---------|-----------------------------------------------------------------------------------| 44 | | a(b\|c) | Encontra uma string que tenha a seguido por b ou c | 45 | | a[bc] | Igual o anterior, ambas as notações podem ser usadas e produzem o mesmo resultado | 46 | 47 | **Classes de caracteres**: `\d`, `\w`, `\s` e `.` 48 | 49 | | Exemplo | Descrição | 50 | |---------|-------------------------------------------------------------------------| 51 | | \d | Encontra um único caracter que seja um dígito | 52 | | \w | Encontra um caracter de palavra (caracter alfanumérico e underline) | 53 | | \s | Encontra caracteres de espaço em branco (incluindo tabs e quebra de linha) | 54 | | . | Encontra qualquer caracter | 55 | 56 | **Negação de classe de caracteres**: `\D`, `\W`, `\S` 57 | 58 | | Exemplo | Descrição | 59 | |---------|-----------------------------------------------------------| 60 | | \D | Faz a operação inversa de \d e traz todos os não-dígitos | 61 | | \W | Faz a operação inversa de \w e traz todas as não-palavras | 62 | | \S | Faz a operação inversa de \s e traz todos os não-espaços | 63 | 64 | Outro ponto importante, é caso queiramos dar **escape**, por exemplo validar um `.`, para isso usamos o `\.` 65 | 66 | O mesmo vale caso seja necessário validarmos `$`, utilizamos `\$` 67 | 68 | Experimente mais opções de expressões em **[Regex101](https://regex101.com/r/cO8lqs/1)** 69 | 70 | ## Expressões Regulares em Python 71 | 72 | Python já possui incluído o módulo **re** que utilizaremos para nossas **expressões regulares**, este módulo fornece operações de correspondência de expressões regulares semelhantes às encontradas em Perl. 73 | 74 | Para usá-lo precisamos importá-lo, sem a necessidade de instalação, vamos também inspecionar o módulo para termos uma visão do que ele nos disponibiliza em termos de atributos e métodos. 75 | 76 | ```python 77 | import re 78 | 79 | print(dir(re)) 80 | # ['A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_alphanum_bytes', '_alphanum_str', '_cache', '_cache_repl', '_compile', '_compile_repl', '_expand', '_locale', '_pattern_type', '_pickle', '_subx', 'compile', 'copyreg', 'error', 'escape', 'findall', 'finditer', 'fullmatch', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template'] 81 | ``` 82 | 83 | Veja que temos bastantes opções para trabalharmos, inicialmente vamos ver os métodos mais relevantes através de diversos exemplos, mas primeiramente é importante entendermos o conceito de *raw string*, pois são elas que vamos utilizar em nossas expressões regulares. 84 | 85 | Uma *raw string* do Python é uma string normal, prefixada com **r** ou **R**. Isso trata caracteres como barra invertida (`\`) como um caractere literal. Isso também significa que esse caractere não será tratado como um caractere de escape, por exemplo: 86 | 87 | ```python 88 | print('Hello\nWorld') 89 | # Hello 90 | # World 91 | ``` 92 | 93 | Veja que o *output* é tratado como esperado, o escape caracter `\n` é interpretado como uma quebra de linha, já no caso de uma *raw string*, ele será tratado como um caractere literal: 94 | 95 | ```python 96 | print(r'Hello\nWorld') # Hello\nWorld 97 | ``` 98 | 99 | Agora que sabemos como as *raw strings* funcionam, vamos ver os métodos de expressões regulares. 100 | 101 | ### findall() 102 | 103 | O método **findall()** retorna todas as porções correspondidas como uma lista de strings. Ele conta com os seguintes argumentos: 104 | 105 | - padrão 106 | - string 107 | - flags 108 | 109 | O primeiro argumento é o padrão que desejamos testar e extrair em relação à string de *input*, que é o segundo argumento. O último argumento flags é opcional. Vamos então aos exemplos para uma melhor compreensão: 110 | 111 | ```python 112 | resultados = re.findall(r'ab*c', 'abc ac adc abbbc abbb') 113 | print(resultados) # ['abc', 'ac', 'abbbc'] 114 | ``` 115 | 116 | No exemplo acima usamos o quantificador `*`, que indica 0 ou mais **b**'s. 117 | 118 | ```python 119 | resultados = re.findall(r'ab+c', 'abc ac adc abbbc abbb') 120 | print(resultados) # ['abc', 'abbbc'] 121 | ``` 122 | 123 | No exemplo acima usamos o quantificador `+`, que indica 1 ou mais **b**'s. 124 | 125 | Vejamos como podemos definir uma expressão regular para encontrar caracteres de palavras: 126 | 127 | ```python 128 | import re 129 | 130 | x = "Expressões regulares são legais" 131 | r = re.findall(r"\w+", x) 132 | print(r) # ['Expressões', 'regulares', 'são', 'legais'] 133 | ``` 134 | 135 | Como podemos ver, todos os caracteres da sentença foram correspondidos e recebemos uma lista deles. 136 | 137 | ### split() 138 | 139 | O método **split()** divida a string pelas ocorrências do padrão. 140 | 141 | ```python 142 | import re 143 | 144 | e = "Eu sou uma expressao com diversas palavras" 145 | r = re.split(r'\s', e) 146 | print(r) # ['Eu', 'sou', 'uma', 'expressao', 'com', 'diversas', 'palavras'] 147 | ``` 148 | 149 | Como podemos ver, a função **split()** separou a expressão em uma lista de palavras, usando o separador `\s` que representa o espaço em branco. 150 | 151 | Vamos agora usar um dígito como separador: 152 | 153 | ```python 154 | string = 'um:1 dois:2 quinze:15 trinta:30' 155 | padrao = r'\d+' 156 | resultado = re.split(padrao, string) 157 | print(resultado) # ['um:', ' dois:', ' quinze:', ' trinta:', ''] 158 | ``` 159 | 160 | ### search() 161 | 162 | Normalmente, usamos o operador **in** para testar se uma string faz parte de outra string ou não. Para expressões regulares, usamos a função **search()** cuja lista de argumentos é mostrada abaixo: 163 | 164 | - padrão 165 | - string 166 | - flags 167 | 168 | O primeiro argumento é o padrão de expressão regular que você deseja testar contra a string de *input*, que é o segundo argumento, flags é opcional, ajuda a alterar o comportamento padrão dos padrões de expressões regulares. 169 | 170 | Como uma boa prática, é interessante usar *raw strings* para construir o padrão de expressão regular. Vejamos então alguns exemplos: 171 | 172 | ```python 173 | import re 174 | 175 | sentenca = "esta é uma string" 176 | 177 | print('esta' in sentenca) # True 178 | print('este' in sentenca) # False 179 | 180 | print(bool(re.search(r'esta',sentenca))) # True 181 | print(bool(re.search(r'este',sentenca))) # False 182 | print(type(re.search(r'esta',sentenca))) # 183 | print(type(re.search(r'este',sentenca))) # 184 | ``` 185 | 186 | O valor de retorno da função **search()** é um objeto `re.Match` quando há uma correspondência, caso contrário o resultado é `NoneType`. 187 | 188 | Vejamos agora um exemplo usando o argumento flags: 189 | 190 | ```python 191 | print(bool(re.search(r'Esta',sentenca))) # False 192 | print(bool(re.search(r'Esta',sentenca, flags=re.I))) # True 193 | ``` 194 | 195 | A flag `re.I` significa **IGNORECASE** é uma flag para permitir correspondência sem distinção entre maiúsculas e minúsculas. 196 | 197 | Vejamos agora um exemplo com expressões geradoras: 198 | 199 | ```python 200 | palavras = ['cachorro','macarrão','macaco'] 201 | 202 | [p for p in palavras if re.search(r'rr',p)] # ['cachorro', 'macarrão'] 203 | all(re.search(r'ca',p) for p in palavras) # True 204 | any(re.search(r'xa',p) for p in palavras) # False 205 | ``` 206 | 207 | Vejamos agora como podemos utilizar um quantificador em nossa padrão: 208 | 209 | ```python 210 | import re 211 | 212 | padrao = "a*b" 213 | r = re.search(padrao, "aaaaaaabcedefg") 214 | print(r) # <_sre.SRE_Match object; span=(0, 8), match='aaaaaaab'> 215 | print(r.group()) # aaaaaaab 216 | ``` 217 | 218 | Como podemos ver, primeiro nos foi retornado um **objeto match**, posteriormente acessamos a string encontrada através do método **group()** que nos traz o resultado, também podemos aplicar métodos como **start()**, **end()** e **span()**. 219 | 220 | ### sub() 221 | 222 | Para busca e substituição normais, podemos usar o método **str.replace()**. Para expressões regulares, usamos a função **sub()**, cuja lista de argumentos é mostrada abaixo: 223 | 224 | - padrão 225 | - substituição 226 | - string 227 | - count 228 | - flags 229 | 230 | O primeiro argumento é o padrão de expressão regular a ser correspondido em relação à string de *input*, que é o terceiro argumento. O segundo argumento específica a string que irá substituir as porções correspondidas pelo padrão da expressão regular. Os últimos dois argumentos são opcionais. Para entendermos melhor este conceito, vamos ao exemplo: 231 | 232 | ```python 233 | frase = 'eu gosto de pizza' 234 | 235 | print(re.sub(r'z','Z',frase)) # eu gosto de piZZa 236 | print(re.sub(r'z','Z',frase,count=1)) # eu gosto de piZza 237 | ``` 238 | 239 | Observe que o argumento **count** limita o número de substituições. 240 | 241 | ### Compilando Expressões Regulares 242 | 243 | Expressões Regulares podem ser compiladas usando a função **compile()**, que nos retorna um objeto `re.Pattern`. 244 | 245 | As funções do módulo **re** de nível superior estão todas disponíveis como métodos para tais objetos. Compilando uma expressão regular é útil se ela tiver que ser usada em vários lugares ou chamada em vários vezes dentro de um loop (benefício de velocidade). 246 | 247 | Vamos começar compilando uma expressão regular: 248 | 249 | ```python 250 | animal = re.compile(r'gato') 251 | print(type(animal)) # 252 | ``` 253 | 254 | Usaremos agora o o método **search()** no padrão definido por nós para buscar pelo padrão em uma determinada string: 255 | 256 | ```python 257 | bool(animal.search('o gato é bonito')) # True 258 | bool(animal.search('o rato é roedor')) # False 259 | ``` 260 | 261 | Também podemos usar o método **sub** neste padrão, de forma a executar substituções: 262 | 263 | ```python 264 | animal.sub('rato','o gato fugiu do cachorro') 265 | # 'o rato fugiu do cachorro' 266 | ``` 267 | 268 | ### match() 269 | 270 | O método **match()** funciona da seguinte forma: Se zero ou mais caracteres no início da string corresponderem a expressão regular informada, retorna um objeto de `re.Match` correspondente. Retorna `None` se a string não corresponder ao padrão. 271 | 272 | Neste exemplo vamos usar um padrão simples para darmos **match** em um email: 273 | 274 | ```python 275 | import re 276 | 277 | padrao = r"\w+@(\w+\.)+(com|org|net)" 278 | r = re.match(padrao,"teste@teste.org") 279 | print(r) # 280 | print(r.group()) # teste@teste.org 281 | ``` 282 | 283 | Vimos que nesse caso, foi possível dar match no e-mail `teste@teste.org`, nos mostrando assim a relevância e importância das expressões regulares dentro da computação, um assunto relevante e de compreensão necessária, pois está presente em praticamente todas as linguagens de programação e sua aplicabilidade é muito vasta. 284 | -------------------------------------------------------------------------------- /content/modulos.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Módulos' 3 | description: 'Aprenda a trabalhar com módulos' 4 | --- 5 | 6 | **Módulo** é um arquivo que contém definições e comandos/instruções **Python**. 7 | 8 | Um módulo pode conter tanto instruções executáveis quanto definições de funções e classes. Essas instruções servem para inicializar o módulo. Eles são executados somente na primeira vez que o módulo é encontrado em uma instrução de importação. 9 | 10 | Podemos dizer que os **módulos** são **bibliotecas** que podem nos ajudar com funções definidas para uso imediato, em outras palavras, para usarmos um módulo devemos compreender como utilizar suas **funções**, sem a necessidade de mergulharmos em **detalhes específicos** de implementação. 11 | 12 | ### Intuição dos Módulos 13 | 14 | Também podemos imaginar um módulo como um conjunto de ferramentas disponíveis para usarmos para solucionar determinados problemas. 15 | 16 | A figura a seguir ilustra esta ideia, onde temos um módulo chamado de **ferramentas**: 17 | 18 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Modules.png) 19 | 20 | Imagine agora que desejamos importar todas as ferramentas do módulo **ferramentas**, para isso, podemos usar o seguinte comando: 21 | 22 | ```python 23 | import ferramentas 24 | ``` 25 | 26 | Agora pense em uma situação em que desejamos apenas importar uma ferramenta específica. Podemos expressar essa ideia da seguinte forma: 27 | 28 | ```python 29 | from ferramentas import martelo 30 | ``` 31 | 32 | Também podemos importar mais de uma ferramenta, separando-as por vírgula: 33 | 34 | ```python 35 | from ferramentas import tesoura, alicate 36 | ``` 37 | 38 | Uma outra maneira de obtermos todas as ferramentas é usando o `*`, neste caso, expressamos da seguinte forma: 39 | 40 | ```python 41 | from ferramentas import * 42 | ``` 43 | 44 | Dessa forma temos todas as ferramentas em mãos e não precisamos usar o prefixo ferramentas quando desejarmos usá-las. 45 | 46 | ### Definindo Módulos 47 | 48 | Vejamos agora como estes conceitos funcionam na prática, para isso vamos definir duas simples funções: 49 | 50 | ```python 51 | def add(x, y): 52 | """Recebe dois números x e y e retorna sua soma""" 53 | return x + y 54 | 55 | def multiply(x, y): 56 | """Recebe dois números x e y e retorna sua multiplicação""" 57 | return x * y 58 | ``` 59 | 60 | Salvamos ambas as funções em um arquivo de nome `modulo.py`, agora vamos criar um **novo arquivo** no mesmo diretório e **importaremos** nosso módulo para utilizá-lo: 61 | 62 | ```python 63 | import modulo 64 | 65 | print(modulo.add(4,5)) # 9 66 | print(modulo.multiply(3,3)) # 9 67 | ``` 68 | 69 | Veja que utilizamos o comando **import** para buscarmos o nosso módulo e posteriormente **invocamos** as funções dele prefixando elas com a palavra **modulo**. 70 | 71 | ### Importando Módulos 72 | 73 | Imagine agora que temos um módulo chamado **matematica**. Os principais formatos para **importarmos** nossos módulos são: 74 | 75 | ```python 76 | import matematica 77 | ``` 78 | 79 | - Tudo que está no módulo **matematica** é importado 80 | - Para se referir aos métodos de matematica, adicionamos o prefixo "matematica" em frente ao seu nome 81 | 82 | ```python 83 | matematica.nomeclasse.metodo() 84 | matematica.funcao() 85 | ``` 86 | 87 | Importando usando o asterisco `*`: 88 | 89 | ```python 90 | from matematica import * 91 | ``` 92 | 93 | - Tudo no módulo matematica é importado 94 | - Para se referir a qualquer método no módulo, basta usar seu nome, sem precisarmos prefixar 95 | - Lembre de ter atenção ao usar esse tipo de import, pois ele pode sobrescrever a definição de uma variável ou função já existente 96 | 97 | ```python 98 | nomeclasse.metodo() 99 | funcao() 100 | ``` 101 | 102 | Importando uma classe ou função específica: 103 | 104 | ```python 105 | from matematica import nomeclasse 106 | ``` 107 | 108 | - Apenas o item **nomeclasse** será importado 109 | - Após importar **nomeclasse** você pode usar ele sem o prefixo do módulo, ele é colocado no namespace atual 110 | - Tome cuidado ao usar, pois pode sobrescrever a definição do nome, caso ele já esteja no namespace 111 | 112 | ```python 113 | nomeclasse.metodo() 114 | funcao() 115 | ``` 116 | 117 | Além de funções, os módulos também podem conter variáveis e estruturas de dados (listas, tuplas, dicionários, objetos). Vamos então criar mais um módulo para testarmos, nomearemos o nosso arquivo como `estudantes.py`. 118 | 119 | ```python 120 | estudantes = [ 121 | {'nome':'Uriel','idade':27,'aprovado':True}, 122 | {'nome':'Emanuel','idade':25,'aprovado':True}, 123 | {'nome':'Malthael','idade':29,'aprovado':False} 124 | ] 125 | 126 | def imprimir_aprovados(): 127 | for estudante in estudantes: 128 | if estudante['aprovado']: 129 | print(f'{estudante["nome"]} está aprovado') 130 | ``` 131 | 132 | Iremos agora importar o módulo **estudantes** e podemos acessar a lista de dicionários **estudantes**, perceba que fornecemos o mesmo nome para ambos, mas isso é uma escolha livre que temos. Também temos acesso a função para imprimir os estudantes que estão aprovados. 133 | 134 | ```python 135 | from estudantes import * 136 | 137 | estudante = estudantes[2]['nome'] 138 | print(estudante) # Malthael 139 | ``` 140 | 141 | Vamos agora invocar a função **imprimir()** para vermos quais estudantes estão aprovados: 142 | 143 | ```python 144 | imprimir() 145 | # Uriel está aprovado 146 | # Emanuel está aprovado 147 | ``` 148 | 149 | Observe que usamos o `*` para importar o módulo por completo, por este motivo não foi necessário prefixarmos a função imprimir da seguinte forma `estudantes.imprimir()`. 150 | 151 | ### Nomeando um Módulo 152 | 153 | Podemos dar um apelido para um módulo, tornando-o mais fácil de nos referirmos a ele, para isso usamos a palavra-chave **as**: 154 | 155 | ```python 156 | import estudantes as e 157 | 158 | print(e.estudantes[0]['idade']) # 27 159 | e.imprimir() 160 | # Uriel está aprovado 161 | # Emanuel está aprovado 162 | ``` 163 | 164 | ### Módulos Construídos do Python 165 | 166 | Existem diversos módulos que já são construídos no Python e nós podemos importá-los quando quisermos sem a necessidade de instalação. 167 | 168 | #### Módulo platform 169 | 170 | O módulo [platform](https://docs.python.org/3/library/platform.html) nos permite o acesso aos dados de identificação da plataforma subjacente. 171 | 172 | ```python 173 | import platform 174 | 175 | s = platform.system() 176 | print(s) # Linux 177 | ``` 178 | 179 | #### A função **dir()** 180 | 181 | Existe uma função muito importante chamada **dir()** que lista todos os nomes das funções (e nome de atributos e variáveis) no módulo. 182 | 183 | Vamos testá-la com o módulo de [math](https://docs.python.org/3/library/math.html): 184 | 185 | ```python 186 | import math 187 | 188 | conteudo = dir(math) 189 | print(conteudo) # ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'] 190 | ``` 191 | 192 | Observe que nos é retornado uma grande quantidade de opções, entre atributos e funções, vejamos como podemos usar algumas delas. 193 | 194 | Calculando a raiz quadrada de um número: 195 | 196 | ```python 197 | print(math.sqrt(4)) # 2.0 198 | ``` 199 | 200 | Calculando o logaritmo na base 2 de um número: 201 | 202 | ```python 203 | print(math.log2(8)) # 3.0 204 | ``` 205 | 206 | Calculando o logaritmo na base 10 de um número: 207 | 208 | ```python 209 | math.log10(100) # 2.0 210 | ``` 211 | 212 | Calculando o máximo divisor comum entre dois números: 213 | 214 | ```python 215 | math.gcd(50,85) # 5 216 | ``` 217 | 218 | Obtendo os valores de **pi** e **e**: 219 | 220 | ```python 221 | print(math.e) # 2.718281828459045 222 | print(math.pi) # 3.141592653589793 223 | ``` 224 | 225 | #### Módulo collections 226 | 227 | Este módulo implementa tipos de dados de contêiner especializados, fornecendo alternativas aos contêineres integrados de uso geral do Python, **dict**, **list**, **set** e **tuple**. 228 | 229 | Imagine que temos por exemplo uma lista com diversos itens repetidos: 230 | 231 | ```python 232 | x = [1,1,1,2,2,3,3,5,9,9] 233 | ``` 234 | 235 | Desejamos contar o número de ocorrências de cada elemento desta lista, podemos usar o **Counter** do módulo [collections](https://docs.python.org/3/library/collections.html): 236 | 237 | ```python 238 | from collections import Counter 239 | 240 | Counter(x) # Counter({1: 3, 2: 2, 3: 2, 9: 2, 5: 1}) 241 | ``` 242 | 243 | Um Counter é uma subclasse de **dict** para a contagem de objetos hashable. É uma coleção onde os elementos são armazenados como chaves de dicionário e suas contagens são armazenadas como valores de dicionário. As contagens podem ser qualquer valor inteiro, incluindo zero ou contagens negativas. 244 | 245 | Observe que o número 1 ocorre 3 vezes, o 2 ocorre 2 e assim por diante. 246 | 247 | Se quisermos saber os dois números com mais entradas, podemos utilizar o método **most_common()** passando como argumento o número 2: 248 | 249 | ```python 250 | Counter(x).most_common(2) # [(1, 3), (2, 2)] 251 | ``` 252 | 253 | Nos será retornado uma lista de tuplas de pares de valores, neste caso indicando que o número 1 ocorre 3 vezes e o 2 apenas 2 vezes. 254 | 255 | #### Módulo statistics 256 | 257 | O módulo [statistics](https://docs.python.org/3/library/statistics.html) fornece funções para calcular estatísticas matemáticas de dados numéricos (com valor real). 258 | 259 | Com ele podemos fazer cálculos como **média**, **mediana**, **moda**, **variância** e **desvio padrão**, essenciais na estatísticas. 260 | 261 | Vamos então importar essas funções específicas e definir uma lista de números reais para exemplificar: 262 | 263 | ```python 264 | from statistics import mean, median, mode, variance, stdev 265 | 266 | y = [-1.0, 2.5, 3.25, 5.75, 12.0, 37.5, 22.8, 99.13, -5.8, 2.5] 267 | ``` 268 | 269 | Calculando a média: 270 | 271 | ```python 272 | media = mean(y) 273 | print(media) # 17.863 274 | ``` 275 | 276 | Calculando a mediana: 277 | 278 | ```python 279 | mediana = median(y) 280 | print(mediana) # 4.5 281 | ``` 282 | 283 | Calculando a moda: 284 | 285 | ```python 286 | moda = mode(y) 287 | print(moda) # 2.5 288 | ``` 289 | 290 | Calculando a variância: 291 | 292 | ```python 293 | variancia = variance(y) 294 | print(variancia) # 977.4160233333333 295 | ``` 296 | 297 | Calculando o desvio padrão: 298 | 299 | ```python 300 | desvio_padrao = stdev(y) 301 | print(desvio_padrao) # 31.263653390692095 302 | 303 | from math import sqrt 304 | 305 | desviopadrao = sqrt(variancia) 306 | print(desviopadrao) # 31.263653390692095 307 | ``` 308 | 309 | Observe que o desvio padrão é apenas a raiz quadrada da variância. 310 | 311 | #### Módulo itertools 312 | 313 | O módulo [itertools](https://docs.python.org/3/library/itertools.html) do Python é uma coleção de ferramentas para lidar com iteradores. Simplificando, iteradores são tipos de dados que podem ser usados em um **for loop**. O iterador mais comum em Python é a lista. 314 | 315 | Para compreendermos melhor o funcionamento deste módulo, vamos considerar alguns exemplos, mas antes vamos importá-lo, abreviando-o com o nome **it**. 316 | 317 | ```python 318 | import itertools as it 319 | ``` 320 | 321 | A função **accumulate()** recebe um iterável como argumento e opcionalmente uma função. Ele retorna os resultados acumulados. Os próprios resultados estão contidos em um iterável. 322 | 323 | ```python 324 | dados = [1,3,4,7,9,25,45] 325 | resultados = it.accumulate(dados) 326 | 327 | for resultado in resultados: 328 | print(f'{resultado} ',end='') # 1 4 8 15 24 49 94 329 | ``` 330 | 331 | Veja que por padrão ele nos traz a soma acumula dos números na sequência, se quisermos por exemplo a multiplicação acumulada, podemos usar a função de multiplicação do módulo **operator** para nos auxiliar nesta tarefa, porém para isso, precisamos importá-lo. Vejamos um exemplo: 332 | 333 | ```python 334 | import operator 335 | 336 | multiplicacoes = it.accumulate(dados,operator.mul) 337 | 338 | for multi in multiplicacoes: 339 | print(f'{multi} ',end='') # 1 3 12 84 756 18900 850500 340 | ``` 341 | 342 | Dessa forma nos será trazida a multiplicação acumulada. 343 | 344 | Outra função muito interessante do módulo itertools é a **combinations()**, esta função recebe um iterável e um inteiro **R** e criará todas as combinações **exclusivas** que possuem **R** membros. 345 | 346 | ```python 347 | formas = ['círculo','triângulo','quadrado','hexágono'] 348 | 349 | R = 2 350 | 351 | combinacoes = it.combinations(formas,R) 352 | 353 | for combinacao in combinacoes: 354 | print(combinacao) 355 | 356 | # ('círculo', 'triângulo') 357 | # ('círculo', 'quadrado') 358 | # ('círculo', 'hexágono') 359 | # ('triângulo', 'quadrado') 360 | # ('triângulo', 'hexágono') 361 | # ('quadrado', 'hexágono') 362 | ``` 363 | 364 | Uma outra função muito interessante de itertools de "força bruta" é **permutations()**, que aceita um único iterável e produz todas as permutações (rearranjos) possíveis de seus elementos: 365 | 366 | ```python 367 | alpha = ['x','y','z'] 368 | 369 | permutacoes = it.permutations(alpha) 370 | 371 | for permutacao in permutacoes: 372 | print(permutacao) 373 | 374 | # ('x', 'y', 'z') 375 | # ('x', 'z', 'y') 376 | # ('y', 'x', 'z') 377 | # ('y', 'z', 'x') 378 | # ('z', 'x', 'y') 379 | # ('z', 'y', 'x') 380 | ``` 381 | 382 | As permutações são todas as maneiras diferentes que podemos agrupar um certo número de itens, onde a ordem importa. 383 | 384 | Qualquer iterável de três elementos terá seis permutações, e o número de permutações de iteráveis mais longos cresce extremamente rápido. Na verdade, um iterável de comprimento `n` possui `n!` permutações, onde: 385 | 386 | ![img](https://raw.githubusercontent.com/the-akira/Python-Iluminado/master/Imagens/Permutations.png) 387 | 388 | Para compreendermos melhor, vejamos uma tabela desses números, de `n = 1` até `n = 10`: 389 | 390 | | n | n! | 391 | |---|---| 392 | | 2 | 2 | 393 | | 3 | 6 | 394 | | 4 | 24 | 395 | | 5 | 120 | 396 | | 6 | 720 | 397 | | 7 | 5040 | 398 | | 8 | 40.320 | 399 | | 9 | 362.880 | 400 | | 10 | 3.628.800 | 401 | 402 | O fenômeno de apenas algumas entradas produzindo um grande número de resultados é chamado de [explosão combinatória](https://en.wikipedia.org/wiki/Combinatorial_explosion). 403 | 404 | A função **cycle()** nos permite criar um ciclo com um determinado iterador: 405 | 406 | ```python 407 | i = 0 408 | 409 | for item in it.cycle([0,1]): 410 | i += 1 411 | if i == 15: 412 | break 413 | print(f'{item} ',end='') 414 | 415 | # 0 1 0 1 0 1 0 1 0 1 0 1 0 1 416 | ``` 417 | 418 | É importante definirmos um ponto de parada para o nosso ciclo, caso contrário ficaremos preso em um loop infinito. 419 | 420 | A função **product()** cria o produto cartesiano de uma série de iteráveis. 421 | 422 | ```python 423 | numeros = [1,2,3] 424 | letras = ['a','b','c'] 425 | 426 | produto = it.product(numeros,letras) 427 | 428 | for p in produto: 429 | print(p) 430 | 431 | # (1, 'a') 432 | # (1, 'b') 433 | # (1, 'c') 434 | # (2, 'a') 435 | # (2, 'b') 436 | # (2, 'c') 437 | # (3, 'a') 438 | # (3, 'b') 439 | # (3, 'c') 440 | ``` 441 | 442 | Como podemos ver os módulos nos permitem organizar o nosso código de maneira limpa e adequada e faz com que possamos trabalhar com bibliotecas do próprio **Python** e até mesmo outras feitas por terceiras pessoas, o que enriquece bastante o leque de possibilidades da linguagem **Python**, nos trazendo muitas funcionalidades adicionais. 443 | --------------------------------------------------------------------------------