├── LICENSE ├── Capitulos ├── 12.Input.md ├── 15.WhileLoops.md ├── 04.Tipos de Variáveis.md ├── 13.If...Else.md ├── 14.ForLoops.md ├── 27.Geradores.md ├── 18.Módulos.md ├── 25.PythonXML.md ├── 26.Iteradores.md ├── 05.Números.md ├── 17.Lambda.md ├── 02.Ambiente de Programação.md ├── 28.Decoradores.md ├── 11.Sets.md ├── 09.Tuplas.md ├── 23.ExpressõesRegulares.md ├── 07.Operadores.md ├── 10.Dicionários.md ├── 24.PythonJSON.md ├── 29.PIP.md ├── 06.Strings.md ├── 01.Introdução.md ├── 03.Sintaxe.md ├── 30.PythonMySQL.md ├── 08.Listas.md ├── 31.PythonMongoDB.md ├── 16.Funções.md ├── 21.DataTempo.md ├── 19.InputOutputArquivos.md └── 20.ErrosExceções.md └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Gabriel Felippe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Capitulos/12.Input.md: -------------------------------------------------------------------------------- 1 | # Input 2 | 3 | Até então todos os nossos programas foram **estáticos**, os valores das variáveis foram definidos por nós no 4 | código fonte, para que haja mais flexibilidade, também é possível que consigamos coletar dados dos usuários. No **Python** temos a opção de usar a função **input()** para capturar dados do usuário. 5 | 6 | ```python 7 | num = input("Insira um número: ") 8 | Insira um número: 3 9 | print(num) # 3 10 | ``` 11 | 12 | Vamos ver qual o tipo de dado que temos em **num** 13 | 14 | ```python 15 | print(type(num)) # 16 | ``` 17 | 18 | Como podemos ver, embora tenhamos digitado um **número**, ele nos retorno uma **string**, para obtermos o número 19 | podemos utilizar as funções **int()** ou **float()** 20 | 21 | ```python 22 | n = int(input("Insira um número: ")) 23 | print(type(n)) # 24 | ``` 25 | 26 | O método **eval()** também é capaz de solucionar o nosso problema e até mesmo resolver expressões, muito bom! 27 | 28 | ```python 29 | eval('2+3') # 5 30 | número = eval(input("Digite um valor: ")) 31 | Digite um valor: 2.3 32 | print(número) # 2.3 33 | print(type(número)) # 34 | ``` 35 | 36 | Como podemos ver, a função **input()** pode nos auxiliar na questão de receber dados de usuários e através dos 37 | diversos métodos vistos, podemos converter os dados recebidos, em breve analisaremos a questão de tratar exceções e erros para evitar problemas de entrada de dados incorretamente. 38 | 39 | **Próximo Capítulo**: [If...Else](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/13.If...Else.md) 40 | -------------------------------------------------------------------------------- /Capitulos/15.WhileLoops.md: -------------------------------------------------------------------------------- 1 | # While Loop 2 | 3 | O **while loop** em **Python** é utilizado para iterar em cima de um bloco de código enquanto determinada expressão (condição) for avaliada como **True**. **While** é normalmente usado quando não sabemos de ante-mão o número de vezes no qual vamos iterar. 4 | 5 | --------------------------------------- 6 | 7 | ## Estrutura Básica do while 8 | 9 | ``` 10 | while : 11 | 12 | 13 | ... 14 | ``` 15 | 16 | - `` é avaliado para um **Booleano** 17 | - se a `` for verdadeira, execute todos os passos dentro do bloco de código while 18 | - checa a `` novamente 19 | - repete até que a `` seja False 20 | 21 | Vejamos um exemplo prático: 22 | 23 | ```python 24 | i = 1 25 | while i < 10: 26 | print(i) 27 | i += 1 # o mesmo que i = i + 1, precisamos dessa expressão, caso contrário teremos um loop infinito 28 | ``` 29 | 30 | A palavra-chave **break** também pode ser utilizada em conjunto com o **while** 31 | 32 | ```python 33 | a = 1 34 | while a < 10 35 | print(a) 36 | if a == 5: 37 | break 38 | a += 1 39 | ``` 40 | 41 | Podemos também usar a palavra-chave **continue** 42 | 43 | ```python 44 | x = 0 45 | while x < 10: 46 | x += 1 47 | if x == 5: 48 | continue 49 | print(x) 50 | ``` 51 | 52 | --------------------------------------- 53 | 54 | ## for vs while 55 | 56 | ### for 57 | 58 | - Número de iterações é **conhecido** 59 | - Pode finalizar antecipadamente através do **break** 60 | - utiliza um **contador** 61 | 62 | ### while 63 | 64 | - Número de iterações **ilimitados** 65 | - Pode finalizar antecipadamente através do **break** 66 | - Pode utilizar um **contador**, porém é necessário inicializar ele antes do loop e incrementá-lo dentro do loop 67 | 68 | Como vimos, **while loops** não são muito misteriosos, porém a utilidade deles pode ser muito grande em nossos programas! 69 | 70 | **Próximo Capítulo**: [Funções](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/16.Fun%C3%A7%C3%B5es.md) 71 | -------------------------------------------------------------------------------- /Capitulos/04.Tipos de Variáveis.md: -------------------------------------------------------------------------------- 1 | # Tipos de Variáveis 2 | 3 | Variáveis são um dos mais importantes conceitos das linguagens de programação. As variáveis são uma localização em memória para guardarmos valores, isso quer dizer que ao criarmos uma variável, estamos reservando espaço em memória para uso futuro, pense na variável como um **container** que podemos guardar dados. 4 | 5 | --------------------------------------- 6 | 7 | ## Atribuindo Valores às Variáveis 8 | 9 | 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. 10 | 11 | ![img](https://i.imgur.com/rYMpGwf.png) 12 | 13 | #### Por exemplo: 14 | 15 | ```python 16 | nome = 'Gabriel' # Uma string 17 | idade = 33 # Um valor inteiro 18 | altura = 1.71 # Um valor em ponto flutuante 19 | 20 | print(nome) 21 | print(idade) 22 | print(altura) 23 | ``` 24 | 25 | #### Também é possível atribuir múltiplos valores para múltiplas variáveis: 26 | 27 | ```python 28 | a, b, c = 5, 3.1, "Hello" 29 | 30 | print(a) 31 | print(b) 32 | print(c) 33 | ``` 34 | 35 | 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: 36 | 37 | ```python 38 | meuNome = "Gabriel" 39 | minhaIdade = 33 40 | meuEndereco = "Avenida Castelo" 41 | ``` 42 | 43 | Letras capitalizadas podem ser usadas para declarar **constantes**, valores que não variam, exemplo: 44 | 45 | ```python 46 | PI = 3.14 47 | GRAVIDADE = 9.8 48 | ``` 49 | 50 | --------------------------------------- 51 | 52 | ## Nomes de Variáveis 53 | 54 | Uma variável pode ter um nome curto (como por exemplo **x** ou **y**) e ou nome mais descritivo (**nome**, **idade**, **resultado**). 55 | 56 | Veja as regras para as variáveis 57 | 58 | - Uma variável deve iniciar com uma letra ou um caracter *underscore* (**_**) 59 | - Uma variável não pode começar com um número 60 | - O nome de uma variável pode conter apenas caracteres alpha-numéricos e *underscores* (A-z, 0-9, e _) 61 | - Nomes de variáveis são *case sensitive* (idade, Idade e IDADE são três variáveis diferentes) 62 | 63 | Agora que você já consegue armazenar valores em variáveis, vamos ver os tipos de dados que existem em **Python** e suas aplicações! 64 | 65 | **Próximo Capítulo**: [Números](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/05.N%C3%BAmeros.md) 66 | -------------------------------------------------------------------------------- /Capitulos/13.If...Else.md: -------------------------------------------------------------------------------- 1 | # If...Else 2 | 3 | Chegamos em um momento muito importante da nossa jornada: **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. 4 | 5 | #### As palavras-chave if...elif...else, são usadas em Python para tomadas de decisão 6 | 7 | Por exemplo 8 | 9 | ```python 10 | num = 5 11 | 12 | if num > 0: 13 | print("O número é positivo") 14 | print("Esse valor é sempre impresso, pois está fora do bloco if") 15 | ``` 16 | 17 | 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**. Também podemos usar a palavra-chave **elif** para testarmos outras possibilidades, uma vez que nem sempre a primeira pode ser atendida. 18 | 19 | ```python 20 | x = 12 21 | y = 12 22 | 23 | if x > y: 24 | print("x é maior do que y") 25 | elif x == y: 26 | print("x e y são iguais") 27 | ``` 28 | 29 | 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. 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. 30 | 31 | ```python 32 | a = 100 33 | b = 20 34 | 35 | if b > a: 36 | print("b é maior do que a") 37 | elif b == a: 38 | print("b e a são iguais") 39 | else: 40 | print("a é maior do que b") 41 | ``` 42 | 43 | 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**. Lembrando que é possível utilizarmos o **else** sem o **elif**. 44 | 45 | ```python 46 | k = 30 47 | z = 22 48 | 49 | if z > k: 50 | print("z é maior do que k") 51 | else: 52 | print("k é maior do que z") 53 | ``` 54 | 55 | Podemos também encadear multiplos **if**...**elif** e **else** 56 | 57 | ```python 58 | # Nesse programa vamos pedir para o usuário entrar com um número 59 | # Avaliaremos se ele é positivo, negativo ou zero e mostraremos ao usuário a mensagem apropriada 60 | 61 | num = int(input("Digite um número: ")) 62 | if num >= 0: 63 | if num == 0: 64 | print("Zero") 65 | else: 66 | print("Número positivo") 67 | else: 68 | print("Número negativo") 69 | ``` 70 | 71 | #### Operadores Lógicos 72 | 73 | Lembram que vimos os **operadores lógicos**, pois eles também podem ser utilizados em conjunto com **if** para 74 | construirmos testes mais complexos 75 | 76 | ```python 77 | n1 = 15 78 | n2 = 30 79 | n3 = 15 80 | ``` 81 | 82 | Operadores **and** e **or** são usados para combinar comandos condicionais 83 | 84 | ```python 85 | if n1 < n2 and n3 == n1: 86 | print("Ambas as condições são verdadeiras") # Será executado, pois ambas as condições se concretizam como True 87 | 88 | if n1 > n2 or n1 == n3: 89 | print("Pelo menos uma condição é verdadeira") # Será executado, mesmo a primeira expressão não sendo avaliada como True, a segunda é avaliada, o que é o suficiente para termos sucesso 90 | ``` 91 | 92 | É importante fixarmos bastante a parte de **tomada de decisão**, pois ela nos dará uma base sólida para construirmos nossos programas, faça testes e experimentos, não se preocupe com possíveis erros. 93 | 94 | **Próximo Capítulo**: [For Loops](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/14.ForLoops.md) 95 | -------------------------------------------------------------------------------- /Capitulos/14.ForLoops.md: -------------------------------------------------------------------------------- 1 | # For Loops 2 | 3 | O **for loop** já é um conhecido nosso, 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 e nos permite percorrer diversas sequências (**listas**, **tuplas**, **dicionários**, **sets** e até mesmo **strings**). 4 | 5 | É válido lembrar que o **for** em **Python** difere um pouco de outras linguagens como por exemplo **C**, onde nós 6 | 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: 7 | 8 | ```python 9 | animais = ["cachorro", "gato", "elefante"] 10 | 11 | for animal in animais: # Utilizamos o nome animal por conveniência, mas você poderia dar o nome que desejar 12 | print(animal) 13 | ``` 14 | 15 | Simples, não? Também podemos percorrer **strings** 16 | 17 | ```python 18 | for x in "eu sou uma string": 19 | print(x) 20 | ``` 21 | 22 | #### A função **range()** 23 | 24 | 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 definamos os passos, o padrão é que seja de 1 em 1. 25 | 26 | 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: 27 | 28 | ```python 29 | x = range(0,10) 30 | print(type(x)) # veja que o tipo retornado é 'range' 31 | print(list(x)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 32 | 33 | y = range(4,30,2) 34 | print(list(y)) # [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28] 35 | ``` 36 | 37 | Podemos aplicar a função **range()** em conjunto com o for 38 | 39 | ```python 40 | for i in range(10): 41 | print(i) 42 | 43 | for data in range(1995,2018): 44 | print(data) 45 | ``` 46 | 47 | A palavra-chave **break** nos permite parar o loop antes que ele passe por todos os itens 48 | 49 | ```python 50 | nomes = ['josé', 'eduardo', 'marcos'] 51 | 52 | for n in nomes: 53 | print(n) 54 | if n == "eduardo": 55 | break 56 | 57 | # Como podemos ver só serão impressos os nomes 'josé' e 'eduardo', quando n tiver o valor de eduardo o loop irá parar e não será capaz de imprimir o nome 'marcos' 58 | ``` 59 | 60 | A palavra-chave **continue** nos permite parar a iteração atual do loop e continuar para a próxima 61 | 62 | ```python 63 | linguagens = ['C', 'Javascript', 'Python', 'Lua'] 64 | 65 | for l in linguagens: 66 | if l == "Javascript": 67 | continue 68 | print(l) 69 | ``` 70 | 71 | 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' 72 | 73 | **Python** nos permite também usarmos a palavra-chave **else** em conjunto com o **for**, por exemplo 74 | 75 | ```python 76 | for x in range(10): 77 | print(x) 78 | else: 79 | print("Loop finalizado com sucesso!") 80 | ``` 81 | 82 | #### Loops encadeados 83 | 84 | Loops encadeados são loops dentro de loops, o "loop de dentro" será executado uma vez para cada iteração do "loop de fora". 85 | 86 | ```python 87 | cores = ['azul', 'verde', 'amarelo'] 88 | num = [1,2,3] 89 | 90 | for c in cores: 91 | for n in num: 92 | print(c,n) 93 | ``` 94 | 95 | Vimos 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()**. 96 | 97 | **Próximo Capítulo**: [While Loops](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/15.WhileLoops.md) 98 | -------------------------------------------------------------------------------- /Capitulos/27.Geradores.md: -------------------------------------------------------------------------------- 1 | # Geradores 2 | 3 | **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. 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. 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, veja o exemplo de uma função geradora. 4 | 5 | ```python 6 | def funcao_geradora(): 7 | for e in range(5): 8 | yield e 9 | 10 | for item in funcao_geradora(): 11 | print(item) 12 | 13 | # 0 14 | # 1 15 | # 2 16 | # 3 17 | # 4 18 | ``` 19 | 20 | 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**. 21 | 22 | Agora veja um gerador que é capaz de calcular números **fibonacci** 23 | 24 | ```python 25 | def fib(n): 26 | a = b = 1 27 | for e in range(n): 28 | yield a 29 | a, b = b, a + b 30 | 31 | for x in fib(7): 32 | print(x) 33 | 34 | # 1 35 | # 1 36 | # 2 37 | # 3 38 | # 5 39 | # 8 40 | # 13 41 | ``` 42 | 43 | ## Expressões geradoras em **Python** 44 | 45 | **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. A sintaxe da expressão geradora nos lembra as **compreensões de lista**, 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. 46 | 47 | ```python 48 | lista = [1, 3, 6, 10, 14] # Inicializamos a lista 49 | 50 | [x**3 for x in lista] # Elevamos ao cubo cada elemento da lista, usando uma compreensão de lista [1, 27, 216, 1000, 2744] 51 | 52 | (x**3 for x in lista) # Fazemos o mesmo com a expressão geradora at 0x7f720eedb3b8> 53 | ``` 54 | 55 | 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. 56 | 57 | ```python 58 | l = [2,3,6,9] # Inicializamos outra lista 59 | 60 | a = (x**4 for x in l) 61 | 62 | print(next(a)) # 16 63 | print(next(a)) # 81 64 | print(next(a)) # 1296 65 | print(next(a)) # 6561 66 | print(next(a)) 67 | 68 | # Traceback (most recent call last): 69 | # File "", line 1, in 70 | # StopIteration 71 | ``` 72 | 73 | Veja que ao atingirmos o limite da lista, o erro **StopIteration** ocorre. 74 | 75 | As **expressões geradoras** também podem ser usadas dentro de funções, veja 76 | 77 | ```python 78 | minha_lista = [4,5,6,7] 79 | 80 | print(sum(x**4 for x in minha_lista)) # 4578 81 | print(max(x**4 for x in minha_lista)) # 2401 82 | ``` 83 | 84 | ## Agora uma questão importante. Por que geradores são usados em Python? 85 | 86 | 1. Fácil de implementar, geradores podem ser implementados de maneira clara e concisa, de forma muito mais simples que os iteradores 87 | 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. 88 | 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. 89 | 90 | **Próximo Capítulo**: [Decoradores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/28.Decoradores.md) 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Python Iluminado

2 | 3 |

4 | Python
5 |

6 | 7 |

8 | Guia para Iniciantes com a Linguagem Python 9 |

10 | 11 | --------------------------------------- 12 | 13 | ## Conteúdo 14 | 15 | 01. [Introdução](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/01.Introdu%C3%A7%C3%A3o.md) 16 | 02. [Ambiente de Programação](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/02.Ambiente%20de%20Programa%C3%A7%C3%A3o.md) 17 | 03. [Sintaxe](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/03.Sintaxe.md) 18 | 04. [Tipos de Variáveis](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/04.Tipos%20de%20Vari%C3%A1veis.md) 19 | 05. [Números](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/05.N%C3%BAmeros.md) 20 | 06. [Strings](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/06.Strings.md) 21 | 07. [Operadores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/07.Operadores.md) 22 | 08. [Listas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/08.Listas.md) 23 | 09. [Tuplas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/09.Tuplas.md) 24 | 10. [Dicionários](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/10.Dicion%C3%A1rios.md) 25 | 11. [Sets](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/11.Sets.md) 26 | 12. [Input](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/12.Input.md) 27 | 13. [If... Else](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/13.If...Else.md) 28 | 14. [For Loops](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/14.ForLoops.md) 29 | 15. [While Loops](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/15.WhileLoops.md) 30 | 16. [Funções](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/16.Fun%C3%A7%C3%B5es.md) 31 | 17. [Expressões Lambda](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/17.Lambda.md) 32 | 18. [Módulos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/18.M%C3%B3dulos.md) 33 | 19. [Input & Output de Arquivos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/19.InputOutputArquivos.md) 34 | 20. [Erros, Exceções e Testes](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/20.ErrosExce%C3%A7%C3%B5es.md) 35 | 21. [Data e Tempo](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/21.DataTempo.md) 36 | 22. [Classes e Objetos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/22.ClassesObjetos.md) 37 | 23. [Expressões Regulares](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/23.Express%C3%B5esRegulares.md) 38 | 24. [JSON](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/24.PythonJSON.md) 39 | 25. [XML](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/25.PythonXML.md) 40 | 26. [Iteradores ](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/26.Iteradores.md) 41 | 27. [Geradores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/27.Geradores.md) 42 | 28. [Decoradores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/28.Decoradores.md) 43 | 29. [Gerenciadores de Pacotes e Ambientes Virtuais](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/29.PIP.md) 44 | 29. [MySQL](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/30.PythonMySQL.md) 45 | 31. [MongoDB](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/31.PythonMongoDB.md) 46 | 32. [Grandes Bibliotecas e Ferramentas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/32.Grandes%20Bibliotecas%20e%20Ferramentas.md) 47 | 33. [Referencias Online](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/33.Refer%C3%AAncias%20Online.md) 48 | -------------------------------------------------------------------------------- /Capitulos/18.Módulos.md: -------------------------------------------------------------------------------- 1 | # Módulos 2 | 3 | **Módulo** é um arquivo que contém definições e comandos **Python**. Podemos dizer que os **módulos** são **bibliotecas** que podem facilitar a nossa vida com funções definidas para uso imediato, em outras palavras, para usarmos um módulo basta entendermos como utilizar suas **funções**, sem a necessidade de mergulharmos em **detalhes específicos** de implementação. Para criarmos um módulo é bastante simples. 4 | 5 | ```python 6 | def oi(): 7 | print("Olá, esse será o seu primeiro módulo!") 8 | ``` 9 | 10 | Salve o arquivo `modulo.py`, agora vamos criar um **novo arquivo** no mesmo diretório e **importaremos** nosso módulo para utilizá-lo 11 | 12 | ```python 13 | import modulo 14 | 15 | modulo.oi() 16 | ``` 17 | 18 | Veja que utilizamos o comando **import** para buscarmos o nosso módulo e posteriormente **invocamos** ele. Os principais formatos para **importarmos** nossos módulos são 19 | 20 | ```python 21 | import arquivo 22 | ``` 23 | - Tudo que está no arquivo é importado 24 | - Para se referir ao métodos do arquivo, adicionamos o texto 'arquivo' em frente ao seu nome 25 | 26 | ```python 27 | arquivo.nomeDaClasse.metodo() 28 | arquivo.minhaFuncao() 29 | ``` 30 | 31 | ```python 32 | from arquivo import * 33 | ``` 34 | - Tudo em arquivo é importado 35 | - Para se referir a qualquer método no módulo, basta usar seu nome 36 | - 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 37 | 38 | ```python 39 | nomeDaClasse.metodo() 40 | minhaFuncao() 41 | ``` 42 | 43 | ```python 44 | from arquivo import nomeDaClasse 45 | ``` 46 | - Apenas o item nomeDaClasse será importado 47 | - Após importar nomeDaClasse você pode usar ele sem o prefixo do módulo, ele é colocado no namespace atual 48 | - Tome cuidado ao usar, pois pode sobrescrever a definição do nome, caso ele já esteja no namespace 49 | 50 | ```python 51 | nomeDaClasse.metodo() 52 | minhaFuncao() 53 | ``` 54 | 55 | Além de funções, os módulos também podem conter variáveis e estruturas de dados (listas, tuplas, dicionários, objetos). Vamos criar mais um módulo para testarmos, vamos nomear o nosso arquivo `pessoa.py` 56 | 57 | ```python 58 | pessoa = { 59 | "nome" : "Pedro", 60 | "idade" : 19, 61 | "nacionalidade" : "portugues" 62 | } 63 | ``` 64 | 65 | Agora importamos o **módulo** pessoa e podemos acessar o **dicionário** pessoa, perceba que demos o mesmo nome para ambos, mas isso é uma escolha livre que temos 66 | 67 | ```python 68 | import pessoa 69 | 70 | p = pessoa.pessoa['nome'] 71 | print(p) 72 | ``` 73 | 74 | #### Nomeando um módulo 75 | 76 | Podemos dar um apelido para o módulo, tornando-o mais fácil de nos referirmos a ele, para isso usamos a palavra-chave **as** 77 | 78 | ```python 79 | import pessoa as p 80 | 81 | x = p.pessoa['nome'] 82 | print(x) 83 | ``` 84 | 85 | #### Módulos construídos do Python 86 | 87 | Existem diversos módulos que já são construídos no Python e nós podemos importá-los quando quisermos 88 | 89 | #### Módulo platform 90 | 91 | ```python 92 | import platform 93 | 94 | s = platform.system() 95 | print(s) # Imprimirá o sistema atual que você está usando, no nosso caso é Linux 96 | ``` 97 | 98 | #### A função **dir()** 99 | 100 | Existe uma função muito importante chamada **dir()** que lista todos os nomes das funções (ou nome de variáveis) no módulo. Vamos testá-la com o módulo de **matemática** 101 | 102 | ```python 103 | import math 104 | 105 | conteudo = dir(math) 106 | 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'] 107 | ``` 108 | 109 | Como podemos ver os módulos nos permitem organizar o nosso código de maneira mais 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 as possibilidades da linguagem **Python** 110 | 111 | **Próximo Capítulo**: [Input/Output de Arquivos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/19.InputOutputArquivos.md) 112 | -------------------------------------------------------------------------------- /Capitulos/25.PythonXML.md: -------------------------------------------------------------------------------- 1 | # XML 2 | 3 | **XML** se refere a *"Extensible Markup Language"*, é uma linguagem de **markup**, 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. 4 | 5 | **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 **<** e termina com **>**. Os caracteres entre a tag de abertura e fechamento, caso tenha algum, é o conteúdo do elemento. 6 | 7 | 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. 8 | 9 | Para entendermos melhor o **XML**, vamos criar um arquivo `menu_alimentos.xml` 10 | 11 | ``` 12 | 13 | 14 | Belgian Waffles 15 | $5.95 16 | 17 | Two of our famous Belgian Waffles with plenty of real maple syrup 18 | 19 | 650 20 | 21 | 22 | Strawberry Belgian Waffles 23 | $7.95 24 | 25 | Light Belgian waffles covered with strawberries and whipped cream 26 | 27 | 900 28 | 29 | 30 | Berry-Berry Belgian Waffles 31 | $8.95 32 | 33 | Light Belgian waffles covered with an assortment of fresh berries and whipped cream 34 | 35 | 900 36 | 37 | 38 | French Toast 39 | $4.50 40 | 41 | Thick slices made from our homemade sourdough bread 42 | 43 | 600 44 | 45 | 46 | Homestyle Breakfast 47 | $6.95 48 | 49 | Two eggs, bacon or sausage, toast, and our ever-popular hash brricao 50 | 51 | 950 52 | 53 | 54 | ``` 55 | 56 | Como podemos ver, ele é fácil de ler, assim como o JSON, agora vamos começar a trabalhar com ele em **Python**, para isso vamos usar o módulo **xml.etree.ElementTree**, 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 fazer o parse. 57 | 58 | ```python 59 | import xml.etree.ElementTree as ET # Veja que aqui vamos nos referir ao módulo como ET 60 | 61 | arvore = ET.parse('menu_alimentos.xml') 62 | raiz = arvore.getroot() 63 | print(raiz) # 64 | print(raiz.tag) # 'menu_alimentos' 65 | print(raiz.attrib) # {}, vazio, pois nesse arquivo XML não utilizamos atributos 66 | 67 | Podemos também percorrer as tags filhas 68 | 69 | for filhas in root: 70 | print(filhas.tag) 71 | # comida 72 | # comida 73 | # comida 74 | # comida 75 | # comida 76 | ``` 77 | 78 | As tags filhas são **encadeadas**, e para acessarmos seus valores específicos por índice, usamos 79 | 80 | ```python 81 | print(root[0][0].text) # Belgian Waffles 82 | ``` 83 | 84 | Agora vamos utilizar o método **Element.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 **Element.find()** que procura o primeiro filho com uma tag particular e **Element.text** que acesso o conteúdo de texto do elemento. O método **Element.get()** acessa os atributos do elemento. 85 | 86 | ```python 87 | for filhas in root.findall('comida'): 88 | alimento = filhas.find('nome').text 89 | print(alimento) 90 | 91 | # Belgian Waffles 92 | # Strawberry Belgian Waffles 93 | # Berry-Berry Belgian Waffles 94 | # French Toast 95 | # Homestyle Breakfast 96 | ``` 97 | 98 | 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 e se necessário como manipulá-lo. 99 | 100 | **Próximo Capítulo**: [Iteradores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/26.Iteradores.md) 101 | -------------------------------------------------------------------------------- /Capitulos/26.Iteradores.md: -------------------------------------------------------------------------------- 1 | # Iteradores 2 | 3 | Iteradores são objetos que podem ser iterados. Nesse guia vamos estudá-lo e aprender como ele funciona construindo um iterador usando os métodos **__iter__** e **__next__**. 4 | 5 | ## O que são os Iteradores, afinal? 6 | 7 | **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. 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. 8 | 9 | Vamos ao experimento, 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**. 10 | 11 | ```python 12 | lista = [1,2,3,4] 13 | 14 | iterador = iter(lista) 15 | 16 | print(next(iterador)) # 1 17 | print(next(iterador)) # 2 18 | print(iterador.__next__()) # 3 19 | print(iterador.__next__()) # 4 20 | 21 | next(iterador) # Sem mais itens para iterar, erro StopIteration ocorre 22 | ``` 23 | 24 | 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. 25 | 26 | ```python 27 | for elemento in lista: 28 | print(lista) 29 | 30 | # 1 31 | # 2 32 | # 3 33 | # 4 34 | ``` 35 | 36 | 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 37 | 38 | ```python 39 | for elemento in iteravel: 40 | # faça algo com o elemento 41 | ``` 42 | 43 | É na verdade: 44 | 45 | ```python 46 | objeto_iteravel = iter(iteravel) # cria um objeto iterador do iteravel 47 | 48 | # Loop infinito 49 | while True: 50 | try: 51 | # pega o novo item 52 | elemento = next(objeto_iteravel) 53 | # faz algo com o elemento 54 | except StopIteration: 55 | # Se o StopIteration ocorrer, break no loop 56 | break 57 | ``` 58 | 59 | 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. 60 | 61 | ## Criando um Iterador 62 | 63 | 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. 64 | 65 | ```python 66 | class Numeros: 67 | def __iter__(self): 68 | self.x = 1 69 | return self 70 | 71 | def __next__(self): 72 | y = self.x 73 | self.x +=1 74 | return y 75 | 76 | n = Numeros() 77 | iterador = iter(n) 78 | 79 | print(next(iterador)) 80 | print(next(iterador)) 81 | print(next(iterador)) 82 | print(next(iterador)) 83 | print(next(iterador)) 84 | 85 | # 1 86 | # 2 87 | # 3 88 | # 4 89 | # 5 90 | ``` 91 | 92 | ## StopIteration 93 | 94 | O exemplo acima pode ser executado infinitamente, especialmente se aplicarmos um **for**. 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. 95 | 96 | ```python 97 | class Numeros: 98 | def __iter__(self): 99 | self.x = 1 100 | return self 101 | 102 | def __next__(self): 103 | if self.x <= 6: 104 | y = self.x 105 | self.x +=1 106 | return y 107 | else: 108 | raise StopIteration 109 | 110 | n = Numeros() 111 | iterador = iter(n) 112 | 113 | for elemento in iterador: 114 | print(elemento) 115 | 116 | # 1 117 | # 2 118 | # 3 119 | # 4 120 | # 5 121 | # 6 122 | ``` 123 | 124 | Esses foram os iteradores, conceito importante e muito presente na nossa jornada, agora vamos continuar **iterando** nosso conhecimento. 125 | 126 | **Próximo Capítulo**: [Geradores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/27.Geradores.md) 127 | -------------------------------------------------------------------------------- /Capitulos/05.Números.md: -------------------------------------------------------------------------------- 1 | # Números 2 | 3 | Em **Python** existem **três** tipos numéricos, são eles: 4 | 5 | - *int* 6 | - *float* 7 | - *complex* 8 | 9 | É importante frizar 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. 10 | 11 | Variáveis do tipo numérico são criadas quando atribuimos valores a elas: 12 | 13 | ```python 14 | a = 27 # int 15 | b = 22.2 # float 16 | c = 3j # complex 17 | ``` 18 | 19 | Para verificarmos qual classe a variável pertence, podemos utilizar a função **type()**: 20 | 21 | ```python 22 | print(type(a)) # 23 | print(type(b)) # 24 | print(type(c)) # 25 | ``` 26 | 27 | --------------------------------------- 28 | 29 | ## Inteiro 30 | 31 | Inteiros são números **positivos**, **negativos**, que não apresentam casas decimais, seu tamanho é limitado apenas pela capacidade de memória disponível: 32 | 33 | ```python 34 | a = 3 35 | b = 342907249723902 36 | c = -100 37 | 38 | print(type(a)) # 39 | print(type(b)) # 40 | print(type(c)) # 41 | ``` 42 | 43 | --------------------------------------- 44 | 45 | ## Float 46 | 47 | Floats ou **"números de ponto flutuante"** são números, positivos ou negativos que podem conter uma ou mais casas decimais: 48 | 49 | ```python 50 | a = 23.3 51 | b = 2.0 52 | c = -17.78 53 | 54 | print(type(a)) # 55 | print(type(b)) # 56 | print(type(c)) # 57 | ``` 58 | 59 | --------------------------------------- 60 | 61 | ## Complex 62 | 63 | Números complexos são escritos com **"j"** como 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. 64 | 65 | Vejamos exemplos 66 | 67 | ```python 68 | a = 2+4j 69 | b = -3j 70 | c = complex(3,4) 71 | 72 | print(type(a)) # 73 | print(type(b)) # 74 | print(type(c)) # 75 | ``` 76 | 77 | ### Obtendo as partes **Real** e **Imaginária** 78 | 79 | ```python 80 | print(c.real) # 3.0 81 | print(c.imag) # 4.0 82 | ``` 83 | 84 | ### Adição 85 | 86 | ```python 87 | x = complex(4,3) 88 | y = complex(-1,4) 89 | z = complex(2,1) 90 | 91 | print(x + y) # (3+7j) 92 | ``` 93 | 94 | Acrescentando um escalar adicionará à **parte real** 95 | 96 | ```python 97 | print(x + 1) # (5+3j) 98 | ``` 99 | 100 | ### Multiplicação 101 | 102 | ```python 103 | print(x * y) # (-16+13j) 104 | ``` 105 | 106 | Multiplicação Escalar 107 | 108 | ```python 109 | print(x * 2) # (8+6j) 110 | ``` 111 | 112 | ### Extensão 113 | 114 | A função `abs(z)` retorna a extensão do número complexo `z`, em outras palavras, ![img](https://www2.clarku.edu/faculty/djoyce/complex/abs1.gif) 115 | 116 | ```python 117 | print(abs(z)) # 2.23606797749979 118 | ``` 119 | 120 | ### Ângulo 121 | 122 | A função `cmath.phase(x)` retorna o ângulo `x` em radianos, para isso teremos que importar a biblioteca **cmath** em nosso código 123 | 124 | ```python 125 | import cmath 126 | 127 | # o resultado estará entre [-π, π] 128 | 129 | print(cmath.phase(x)) # 0.6435011087932844 130 | print(phase(complex(-1.0, 0.0))) # 3.1415926535897931 131 | print(phase(complex(-1.0, -0.0))) # -3.1415926535897931 132 | ``` 133 | 134 | ### Constante π and e 135 | 136 | ```python 137 | print(cmath.pi) # 3.141592653589793 138 | print(cmath.e) # 2.718281828459045 139 | ``` 140 | 141 | --------------------------------------- 142 | 143 | ## Números Aleatórios 144 | 145 | 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: 146 | 147 | ```python 148 | import random 149 | 150 | print(random.randrange(1,10)) # Gera números entre 1 e 9 151 | ``` 152 | 153 | Caso queira saber mais detalhes sobre o módulo `random` você pode visitar sua **[Referência](https://www.w3schools.com/python/module_random.asp)** 154 | 155 | --------------------------------------- 156 | 157 | ## Conversão de Números 158 | 159 | ```python 160 | k = 3 161 | i = 7.7 162 | z = 4j 163 | 164 | print(type(k),type(i),type(z)) # 165 | 166 | # Convertendo de int para float 167 | print(float(k)) # 3.0 168 | 169 | # Convertendo de float para int 170 | print(int(i)) # 7 171 | 172 | # Convertendo de int para complex 173 | print(complex(k)) # (3+0j) 174 | ``` 175 | 176 | Importante lembrar que não podemos converter um número complexo para outro tipo numérico. 177 | 178 | Lembre sempre que números são um **elemento essencial** na programação e que vamos utilizar muito eles! 179 | 180 | **Próximo Capítulo**: [Strings](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/06.Strings.md) 181 | -------------------------------------------------------------------------------- /Capitulos/17.Lambda.md: -------------------------------------------------------------------------------- 1 | # Expressões Lambda 2 | 3 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Lambda_uc_lc.svg/100px-Lambda_uc_lc.svg.png) 4 | 5 | **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**. 6 | 7 | Python e outras linguagens como Java, C# e até mesmo C++ estiveram as funções lambda adicionadas a sua sintáxe, 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. 8 | 9 | Expressões Lambda em Python e em outras linguagens de programação possuem suas raízes no **cálculo lambda**, um modelo de computação inventando por **[Alonzo Church](https://en.wikipedia.org/wiki/Alonzo_Church)** 10 | 11 | - 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 12 | - Uma função anônima não pode ser chamada diretamente pela função **print()**, pois ela requer uma expressão 13 | 14 | ## Funções Anônimas 15 | 16 | Os seguintes termos são usados de forma de forma intercambiável dependendo da linguagem de programação ou local que você vive 17 | 18 | - Funções Anônimas 19 | - Funções Lambda 20 | - Expressões Lambda 21 | - Abstrações Lambda 22 | - Forma Lambda 23 | - Literais de Função 24 | 25 | --------------------------------------- 26 | 27 | ## Fundamentos Básicos 28 | 29 | A estrutura para utilizarmos as funções lambdas é muito simples 30 | 31 | ``` 32 | lambda argumento1, argumento2, argumento3: expressão 33 | ``` 34 | 35 | Por exemplo: 36 | 37 | ```python 38 | triplo = lambda x: x * 3 39 | print(triplo(3)) # 9 40 | ``` 41 | 42 | ```python 43 | quadrado = lambda x: x * x 44 | print(quadrado(5)) # 25 45 | ``` 46 | 47 | ```python 48 | nome_completo = lambda nome,sobrenome: nome.strip().title() + " " + sobrenome.strip().title() 49 | print(nome_completo('Victor','Hugo')) 50 | ``` 51 | 52 | Podemos também usar **condicionais** com funções Lambda 53 | 54 | ```python 55 | comeca_com_G = lambda x: True if x.startswith('G') else False 56 | print(comeca_com_G('Gabriel')) # True 57 | print(comeca_com_G('Rafael')) # False 58 | ``` 59 | 60 | ```python 61 | palavra_antes = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None 62 | sentenca = 'Rato Roeu Roupa Rei Roma' 63 | print(palavra_antes(sentenca,'Roma')) # Rei 64 | ``` 65 | 66 | --------------------------------------- 67 | 68 | ## Usos da função lambda em Python 69 | 70 | Nós normalmente usamos elas 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). **Funções lambda** podem ser usadas com outras funções pré-construídas, como **filter()**, **map()**, etc. 71 | 72 | ### Filtrando 73 | 74 | Por exemplo, com **filter()**, que recebe uma função e uma lista como argumento 75 | 76 | ```python 77 | lista = [1,2,3,4,5] 78 | 79 | nova_lista = list(filter(lambda x: (x % 2 == 0), lista)) 80 | 81 | # 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 na nossa nova lista, formando assim uma lista de números pares 82 | 83 | print(nova_lista) # [2, 4] 84 | ``` 85 | 86 | ### Mapeando 87 | 88 | Por exemplo, com **map()**, que também recebe uma função e uma lista como argumento 89 | 90 | ```python 91 | lst = [3,5,6,7,9] 92 | 93 | nova_lst = list(map(lambda y: y * 10, lst)) # Dessa vez a expressão lambda multiplicará cada item da lista por 10 e estes serão mapeados em uma nova lista 94 | 95 | print(nova_lst) # [30, 50, 60, 70, 90] 96 | ``` 97 | 98 | ### Ordenando 99 | 100 | Através do método **sort()** podemos por exemplo organizar uma **lista** com uma expressão lambda. Vejamos um exemplo da ideia 101 | 102 | ```python 103 | alimentos = [('ovos', 10),('pães', 5),('tomate', 6),('cenoura', 4),('maçã', 3)] 104 | alimentos.sort(key = lambda x: x[0]) 105 | print(alimentos) 106 | # [('cenoura', 4), ('maçã', 3), ('ovos', 10), ('pães', 5), ('tomate', 6)] 107 | alimentos.sort(key = lambda x: x[1]) 108 | print(alimentos) 109 | # [('maçã', 3), ('cenoura', 4), ('pães', 5), ('tomate', 6), ('ovos', 10)] 110 | ``` 111 | 112 | ### Função que cria Funções 113 | 114 | É possível criarmos uma função que nos **retorna** uma expressão lambda para assim trabalharmos 115 | 116 | ```python 117 | # Função que cria funções 118 | def construcao_quadraticas(a, b, c): 119 | """Retorna a função f(x) = ax^2 + bx + c""" 120 | return lambda x: a*x**2 + b*x + c 121 | 122 | # Constrói uma nova função com os parâmetros (4,7,-6) 123 | f = construcao_quadraticas(4,7,-6) 124 | 125 | print(f(0)) # -6 126 | print(f(3)) # 51 127 | ``` 128 | 129 | --------------------------------------- 130 | 131 | Muito legal e útil, não? **Expressões lambdas** podem agilizar bastante nossa vida. 132 | 133 | **Próximo Capítulo**: [Módulos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/18.M%C3%B3dulos.md) 134 | -------------------------------------------------------------------------------- /Capitulos/02.Ambiente de Programação.md: -------------------------------------------------------------------------------- 1 | # Ambiente de Programação 2 | 3 | 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. 4 | 5 | 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: 6 | 7 | ``` 8 | python --version 9 | ``` 10 | 11 | --------------------------------------- 12 | 13 | ## Antes de começarmos a programar: 14 | 15 | É de extrema importância que tenhamos um editor de texto eficiente e leve, para isso existem muitas opções excelentes: 16 | 17 | - [Sublime Text](https://www.sublimetext.com/) 18 | - [Atom](https://atom.io/) 19 | - [Brackets](http://brackets.io/) 20 | - [Notepad++](https://notepad-plus-plus.org/) 21 | - [Gedit](https://wiki.gnome.org/Apps/Gedit) 22 | - [Visual Studio Code](https://code.visualstudio.com/) 23 | - [Vim](https://www.vim.org/) 24 | - [Light Table](http://lighttable.com/) 25 | - [GNU Emacs](https://www.gnu.org/software/emacs/) 26 | 27 | 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: 28 | 29 | - [Thonny](https://thonny.org/) 30 | - [PyCharm](https://www.jetbrains.com/pycharm/download/) 31 | - [IPython](https://ipython.org/) 32 | - [PyDev](http://www.pydev.org/) 33 | - [Spyder](https://www.spyder-ide.org/) 34 | 35 | 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! 36 | 37 | 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*: 38 | 39 | ```python 40 | print("Hello World") 41 | ``` 42 | 43 | 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 o Sublime Text está configurado para interpretar todos os nossos *scripts*, para executarmos ele devemos ir até **Tools -> Build** ou através do atalho `CTRL + B`. 44 | 45 | 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**! 46 | 47 | --------------------------------------- 48 | 49 | ## Python Interativo 50 | 51 | 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: 52 | 53 | ```python 54 | python3 55 | ``` 56 | 57 | Aparecerão algumas informações, como a versão do Python, sua data e você verá **`>>>`**, esse é o **interpretador** do Python, agora é só digitarmos: 58 | 59 | ```python 60 | >>> print("Hello World") 61 | ``` 62 | 63 | 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: 64 | 65 | ```python 66 | >>> help(float) # Nos trará informações sobre a classe float 67 | >>> help(print) # Nos trará informações sobre a função print 68 | ``` 69 | 70 | --------------------------------------- 71 | 72 | ## Filosofia Python 73 | 74 | Para conhecer a Grande Filosofia da Linguagem Python você pode digitar: 75 | 76 | ```python 77 | >>> import this 78 | ``` 79 | 80 | Nos será retornado: 81 | 82 | ``` 83 | The Zen of Python, by Tim Peters 84 | 85 | Beautiful is better than ugly. 86 | Explicit is better than implicit. 87 | Simple is better than complex. 88 | Complex is better than complicated. 89 | Flat is better than nested. 90 | Sparse is better than dense. 91 | Readability counts. 92 | Special cases aren't special enough to break the rules. 93 | Although practicality beats purity. 94 | Errors should never pass silently. 95 | Unless explicitly silenced. 96 | In the face of ambiguity, refuse the temptation to guess. 97 | There should be one-- and preferably only one --obvious way to do it. 98 | Although that way may not be obvious at first unless you're Dutch. 99 | Now is better than never. 100 | Although never is often better than *right* now. 101 | If the implementation is hard to explain, it's a bad idea. 102 | If the implementation is easy to explain, it may be a good idea. 103 | Namespaces are one honking great idea -- let's do more of those! 104 | ``` 105 | 106 | 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 107 | 108 | Para sair do **interpretador** basta digitar **exit()** ou **quit()**. Agora já estamos prontos para mergulhar em mares mais profundos e explorar as diversas capacidades que **Python** tem a nos oferecer! 109 | 110 | **Próximo Capítulo**: [Sintaxe](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/03.Sintaxe.md) 111 | -------------------------------------------------------------------------------- /Capitulos/28.Decoradores.md: -------------------------------------------------------------------------------- 1 | # Decoradores 2 | 3 | **Decoradores** são uma parte *significante do Python*, também são conhecidos como **meta-programação**, 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. 4 | 5 | ```python 6 | def oi(nome="Pedro"): 7 | return "Oi " + nome 8 | 9 | print(oi()) # Oi Pedro 10 | 11 | ola = oi # Podemos atribuir uma função a uma variável, não usamos parenteses, pois não estamos chamando a função 12 | 13 | print(ola()) # Oi Pedro 14 | 15 | del oi # Agora vamos deletar a antiga função 16 | 17 | print(oi()) 18 | 19 | # Traceback (most recent call last): 20 | # File "", line 1, in 21 | # NameError: name 'oi' is not defined 22 | 23 | print(ola()) # Oi Pedro 24 | ``` 25 | 26 | Veja que mesmo deletando a função antiga, ainda conseguimos executar a função **ola()** 27 | 28 | ## Funções dentro de funções 29 | 30 | Agora que relembramos o *básico das funções*, vamos nos aprofundar um pouco mais com a possibilidade que Python nos permite, definir funções dentro de outras funções 31 | 32 | ```python 33 | def oi(name="Paulo"): 34 | print("Aqui estamos dentro da função oi()") 35 | 36 | def ola(): 37 | return "aqui você está na função ola()" 38 | 39 | def boasvindas(): 40 | return "aqui você está na função boasvindas()" 41 | 42 | print(ola()) 43 | print(boasvindas()) 44 | print("agora estamos novamente na função oi()") 45 | 46 | oi() 47 | 48 | # Aqui estamos dentro da função oi() 49 | # aqui você está na função ola() 50 | # aqui você está na função boasvindas() 51 | # agora estamos novamente na função oi() 52 | 53 | ola() 54 | 55 | # Traceback (most recent call last): 56 | # File "deco.py", line 15, in 57 | # ola() 58 | # NameError: name 'ola' is not defined 59 | ``` 60 | 61 | Perceba que não conseguimos chamar a função **ola()** diretamente, porém a ideia que queriamos ilustrar é a capacidade de **encadearmos** **funções dentro de funções**, agora vamos para um passo importante, outra capacidade importante das funções. 62 | 63 | É importante lembrarmos que funções podem ser passadas como argumentos para outra função, já vimos isso de forma breve no passado com as funções **map**, **filter**, etc. Funções com essa capacidade são chamadas de função de **high order**, vejamos: 64 | 65 | ```python 66 | def inc(x): 67 | return x + 1 68 | 69 | def dec(x): 70 | return x - 1 71 | 72 | def operacao(func, x): 73 | resultado = func(x) 74 | return resultado 75 | 76 | operacao(inc,5) # 6 77 | operacao(dec,10) # 9 78 | ``` 79 | 80 | **Importante**, funções também podem retornar outra função: 81 | 82 | ```python 83 | def chamada(): 84 | def retornada(): 85 | print("Olá") 86 | return retornada 87 | 88 | nova = chamada() 89 | nova() # Olá 90 | ``` 91 | 92 | Veja que **retornada()** é uma função encadeada que é definida e retornada cada vez que chamamos **chamada()** 93 | 94 | ## Vamos aos decoradores 95 | 96 | Funções e métdos 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*. Então como já tinhamos dito na nossa introdução, um decorador recebe um função, adiciona alguma funcionalidade a ela e a retorna. 97 | 98 | ```python 99 | def embelezar(func): 100 | def interno(): 101 | print("Fui decorado") 102 | func() 103 | return interno 104 | 105 | def normal(): 106 | print("Eu sou normal") 107 | 108 | normal() # Eu sou normal 109 | bonito = embelezar(normal) 110 | bonito() 111 | # Fui decorado 112 | # Eu sou normal 113 | ``` 114 | 115 | 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 116 | 117 | ```python 118 | @embelezar 119 | def normal(): 120 | print("Eu sou normal também") 121 | 122 | normal() 123 | 124 | # Fui decorado 125 | # Eu sou normal também 126 | ``` 127 | 128 | ## Decorando Funções com Parâmetros 129 | 130 | A ú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? 131 | 132 | ```python 133 | def divisao(x, y): 134 | return x / y 135 | ``` 136 | 137 | A função recebe dois parâmetros **x** e **y**, sabemos que se passarmos **0** para **y** ocorrerá um erro. 138 | 139 | ```python 140 | print(divisao(10,2)) # 5.0 141 | print(divisao(3,0)) # ZeroDivisionError: division by zero 142 | ``` 143 | 144 | Agora vamos fazer um decorador para resolvermos esse problema 145 | 146 | ```python 147 | def divisao_inteligente(func): 148 | def interior(x,y): 149 | print("Será feita uma divisão de {0} por {1}".format(x,y)) 150 | if y == 0: 151 | print("Impossível dividir") 152 | return 153 | return func(x,y) 154 | return interior 155 | 156 | @divisao_inteligente 157 | def divisao(x,y): 158 | return x / y 159 | 160 | divisao(3,3) 161 | # Será feita uma divisão de 3 por 3 162 | # 1.0 163 | divisao(3,0) 164 | # Será feita uma divisão de 3 por 0 165 | # Impossível dividir 166 | ``` 167 | 168 | Dessa forma podemos decorar funções que recebem parâmetros, trazendo a nós uma grande gama de novas possibilidades. Sendo assim, observamos que decoradores são de certa forma um pouco complexos, mas que nos trazem novas possibilidades de trabalharmos em cima de funções. Eles são muito comuns também em **frameworks web**, como **flask** e **bottle** por exemplo. 169 | 170 | **Próximo Capítulo**: [PIP](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/29.PIP.md) 171 | -------------------------------------------------------------------------------- /Capitulos/11.Sets.md: -------------------------------------------------------------------------------- 1 | # Sets 2 | 3 | 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 **{}**. Cuidado para não confundir os Sets com os dicionários! 4 | 5 | Talvez você lembre dos Sets através da **[famosa teoria matemática dos conjuntos](https://pt.wikipedia.org/wiki/Teoria_dos_conjuntos)** 6 | 7 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Venn_A_subset_B.svg/150px-Venn_A_subset_B.svg.png) 8 | 9 | Os Sets podem ser usados para executarmos operações matemáticas de conjuntos como **união**, **intersecção**, **diferença simétrica**, etc. 10 | 11 | --------------------------------------- 12 | 13 | ## Definindo um Set 14 | 15 | ```python 16 | s = {1,1,2,3,3,4} 17 | print(type(s)) # 18 | print(s) # {1, 2, 3, 4} Veja que os valores repetidos foram eliminados 19 | ``` 20 | 21 | Também podemos criar através do método **set()** 22 | 23 | ```python 24 | k = set([1,2,3,4,5]) 25 | print(type(k)) # 26 | print(k) # {1, 2, 3, 4, 5} 27 | ``` 28 | 29 | --------------------------------------- 30 | 31 | ## Operações com Sets 32 | 33 | O método **add()** nos possibilita adicionar um item ao Set 34 | 35 | ```python 36 | k.add(8) 37 | print(k) # {1, 2, 3, 4, 5, 8} 38 | ``` 39 | 40 | O método **discard()** nos permite remover itens de um Set 41 | 42 | ```python 43 | s.discard(1) 44 | print(s) # {2, 3, 4} 45 | ``` 46 | 47 | Para remover todos os elementos do Set podemos usar o método **clear()** 48 | 49 | ```python 50 | k.clear() 51 | print(k) # set() 52 | ``` 53 | 54 | Vamos agora definir dois novos Sets `x` e `y` para testarmos **novas operações** 55 | 56 | ```python 57 | x = {1,2,3} 58 | y = {2,3,4} 59 | ``` 60 | 61 | ### Intersecção 62 | 63 | Para intersecção podemos usar `&` ou o método **intersection()** 64 | 65 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Venn0001.svg/220px-Venn0001.svg.png) 66 | 67 | ```python 68 | print(x & y) # {2, 3} 69 | print(x.intersection(y)) # {2, 3} 70 | ``` 71 | 72 | ### Diferença 73 | 74 | Para diferença podemos usar `-` ou o método **difference()** 75 | 76 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Venn0100.svg/220px-Venn0100.svg.png) 77 | 78 | ```python 79 | # Relativo a x 80 | print(x - y) # {1} 81 | x.difference(y) # {1} 82 | 83 | # Relativo a y 84 | print(y - x) # {4} 85 | y.difference(x) # {4} 86 | ``` 87 | 88 | ### Diferença Simétrica 89 | 90 | Para diferença simétrica podemos usar `^` ou o método **symmetric_difference()** 91 | 92 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Venn0110.svg/220px-Venn0110.svg.png) 93 | 94 | ```python 95 | # Todos imprimem o mesmo resultado, uma vez que a diferença é simétrica 96 | 97 | print(x.symmetric_difference(y)) # {1, 4} 98 | print(y.symmetric_difference(x)) # {1, 4} 99 | print(x ^ y) # {1, 4} 100 | print(y ^ x) # {1, 4} 101 | ``` 102 | 103 | ### União 104 | 105 | Para união podemos usar `|` ou o método **union()** 106 | 107 | ![img](https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Venn0111.svg/220px-Venn0111.svg.png) 108 | 109 | ```python 110 | print(x | y) # {1, 2, 3, 4} 111 | print(x.union(y)) # {1, 2, 3, 4} 112 | ``` 113 | 114 | ### Verificando a presença de um Elemento 115 | 116 | ```python 117 | print(1 in x) # True 118 | print(5 in x) # False 119 | ``` 120 | 121 | --------------------------------------- 122 | 123 | ## Referência Sets 124 | 125 | Os Sets nos trazem diversas funcionalidades e nos permitem resolver diversos problemas, para conhecer mais detalhes sobre eles visite a **[documentação](https://docs.python.org/3/tutorial/datastructures.html#sets)** 126 | 127 | | Método | Descrição | 128 | |-------------------------------|:--------------------------------------------------------------------------------:| 129 | | add() | Adiciona um elemento ao set | 130 | | clear() | Remove todos os elementos do set | 131 | | copy() | Retorna uma cópia do set | 132 | | difference() | Retorna um set contendo a diferença entre dois ou mais sets | 133 | | difference_update() | Remove os itens desse set que também estão incluídos em outro set especificado | 134 | | discard() | Remove um item específico | 135 | | intersection() | Retorna um set que é intersecção entre dois sets | 136 | | intersection_update() | Remove os itens desse set que não estão presente em outro set especificado | 137 | | isdisjoint() | Retorna se dois sets possuem intersecção ou não | 138 | | issubset() | Retorna se outro set contém esse set ou não | 139 | | issuperset() | Retorna se esse set contém outro set ou não | 140 | | pop() | Remove o item especificado | 141 | | remove() | Remove o item especificado | 142 | | symmetric_difference() | Retorna um set com a diferença simétrica de dois sets | 143 | | symmetric_difference_update() | Insere a diferença simétrica desse set e outro | 144 | | union() | Retorna um set contendo a união de sets | 145 | | update() | Atualiza o set com a união desse set e outros | 146 | 147 | **Próximo Capítulo**: [Input](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/12.Input.md) 148 | -------------------------------------------------------------------------------- /Capitulos/09.Tuplas.md: -------------------------------------------------------------------------------- 1 | # Tuplas 2 | 3 | Tuplas são uma sequência de **objetos imutáveis**, em outras palavras, uma vez criadas, tuplas não podem 4 | ser modificadas, normalmente são usadas para guardar **dados protegidos**. As tuplas são escritas entre 5 | parênteses **()**. 6 | 7 | --------------------------------------- 8 | 9 | ## Criando uma tupla 10 | 11 | ```python 12 | tupla = ("python", "ruby", "perl") 13 | print(tupla) # ('python', 'ruby', 'perl') 14 | ``` 15 | 16 | --------------------------------------- 17 | 18 | ## Acessando itens 19 | 20 | ```python 21 | print(tupla[0:2]) # ('python', 'ruby') 22 | print(tupla[-1]) # perl 23 | ``` 24 | 25 | --------------------------------------- 26 | 27 | ## Atualizando Tuplas 28 | 29 | Como já mencionado, Tuplas são imutáveis, ou seja, não podemos alterar os seus elementos, porém podemos 30 | pegar porções de uma tupla e criar novas tuplas, por exemplo 31 | 32 | ```python 33 | tup1 = (1,2) 34 | tup2 = (3,4) 35 | 36 | tup1[0] = 5 # Provocará um erro 37 | 38 | tup3 = tup1 + tup2 39 | print(tup3) # (1,2,3,4) 40 | ``` 41 | 42 | --------------------------------------- 43 | 44 | ## Percorrendo através dos itens de uma Tupla 45 | 46 | ```python 47 | t = (1,2,3) 48 | 49 | for x in t: # Percorre os valores da tupla t 50 | print(x) # Imprime os valores de t 51 | ``` 52 | 53 | --------------------------------------- 54 | 55 | ## Checando se determinado item está presente na Tupla 56 | 57 | ```python 58 | print(1 in t) # True 59 | ``` 60 | 61 | ```python 62 | print(5 in t) # False 63 | ``` 64 | 65 | --------------------------------------- 66 | 67 | ## Verificando o tamanho de uma Tupla 68 | 69 | ```python 70 | print(len(t)) # 3 71 | ``` 72 | 73 | --------------------------------------- 74 | 75 | ## del 76 | 77 | Embora seja impossível remover itens da Tupla, é possível deletá-la por completo 78 | 79 | ```python 80 | del t 81 | print(t) # Ocorrerá um erro, uma vez que a tupla t não existe mais 82 | ``` 83 | 84 | --------------------------------------- 85 | 86 | ## Construtor tuple() 87 | 88 | Somos capazes também de construir uma Tupla com o método **tuple()** 89 | 90 | ```python 91 | tup = tuple((6,7,8)) 92 | print(tup) # (6, 7, 8) 93 | ``` 94 | 95 | --------------------------------------- 96 | 97 | ## Método count() 98 | 99 | O método **count()** nos retorna a quantidade de vezes que determinado valor ocorre em uma tupla 100 | 101 | ```python 102 | print(tup.count(6)) # 1 103 | ``` 104 | 105 | --------------------------------------- 106 | 107 | ## Método index() 108 | 109 | O método **index()** nos permite buscar por um determinado e nos retorna o índice dele 110 | 111 | ```python 112 | print(tup.index(6)) # 0 113 | ``` 114 | 115 | --------------------------------------- 116 | 117 | ## Criando uma Função que Retorna uma Tupla 118 | 119 | Funções sempre 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. Vejamos um exemplo para ilustrar a ideia: 120 | 121 | ```python 122 | import math 123 | 124 | def f(r): 125 | """ Retorna (circunferência, área) de um círculo de raio r """ 126 | c = 2 * math.pi * r 127 | a = math.pi * r * r 128 | return (c, a) 129 | 130 | print(f(5)) 131 | print(f(8)) 132 | ``` 133 | 134 | --------------------------------------- 135 | 136 | ## Named Tuples 137 | 138 | **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`. Vejamos exemplos: 139 | 140 | ```python 141 | # É muito comum representarmos um ponto como uma tupla (x, y) 142 | from math import sqrt 143 | 144 | p1 = (2.0, 7.0) 145 | p2 = (2.5, 3.5) 146 | 147 | comprimento_linha = sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2) 148 | 149 | print(comprimento_linha) 150 | ``` 151 | 152 | Ao utilizarmos uma Named Tuple, nosso código se torna mais legível 153 | 154 | ```python 155 | from collections import namedtuple 156 | 157 | Ponto = namedtuple('Point', 'x y') 158 | p1 = Ponto(1.5, 5.0) 159 | p2 = Ponto(4.5, 1.5) 160 | 161 | comprimento_da_linha = sqrt((p1.x-p2.x)**2 + (p1.y-p2.y)**2) 162 | print(comprimento_da_linha) 163 | ``` 164 | 165 | Armazenando cores **RGB** com Named Tuples 166 | 167 | ```python 168 | Cor = namedtuple('Cor', ['red', 'green', 'blue']) 169 | 170 | cor = Cor(55,155,255) 171 | 172 | print(cor) # Cor(red=55, green=155, blue=255) 173 | print(cor.red) # 55 174 | ``` 175 | 176 | --------------------------------------- 177 | 178 | ## Tuplas vs Listas 179 | 180 | Por que devemos usar uma Tupla ao invés de uma Lista? 181 | 182 | - A execução do programa é mais rápida quando manipulamos uma tupla do que uma equivalente lista. 183 | - As vezes desejamos que os dados não sejam modificados, se determinados valores em uma coleção devem ser constantes no programa, utilizar uma Tupla nos protege contra acidentes de modificação 184 | 185 | ### Exemplos 186 | 187 | ```python 188 | # Exemplo de Lista 189 | numeros_primos = [2, 3, 5, 7, 11, 13, 17] 190 | 191 | # Exemplo de Tupla 192 | quadrados_perfeitos = (1, 4, 9, 16, 25, 36) 193 | 194 | # Mostrar os tamanhos 195 | print(f'# Primos: {len(numeros_primos)}') 196 | print(f'# Quadrados Perfeitos: {len(quadrados_perfeitos)}') 197 | 198 | # Iterar sob as sequencias 199 | for p in numeros_primos: 200 | print(f'Primos: {p}') 201 | 202 | for n in quadrados_perfeitos: 203 | print(f'Primos: {n}') 204 | ``` 205 | 206 | ### Métodos das Listas e Tuplas 207 | 208 | ```python 209 | # Métodos 210 | print('Métodos Lista') 211 | print(dir(numeros_primos)) 212 | print('Métodos Tupla') 213 | print(dir(quadrados_perfeitos)) 214 | ``` 215 | 216 | ### Obtendo o tamanho em Bytes 217 | 218 | ```python 219 | lista_ex = [1, 2, 3, 'x', 'y', 'z', True, 3.14159] 220 | tupla_ex = (1, 2, 3, 'x', 'y', 'z', True, 3.14159) 221 | 222 | print(f'Tamanho da lista = {sys.getsizeof(lista_ex)}') 223 | print(f'Tamanho da tupla = {sys.getsizeof(tupla_ex)}') 224 | ``` 225 | 226 | ### Comparando o Tempo 227 | 228 | ```python 229 | lista_teste = timeit.timeit(stmt='[1,2,3,4,5]', number=1_000_000) 230 | tupla_teste = timeit.timeit(stmt='(1,2,3,4,5)', number=1_000_000) 231 | 232 | print(f'Tempo da lista: {lista_teste}') 233 | print(f'Tempo da tupla: {tupla_teste}') 234 | ``` 235 | 236 | --------------------------------------- 237 | 238 | Como podemos ver, as **tuplas** são uma estrutura de dados **imutável** e **rápida** que pode nos auxiliar bastante. 239 | 240 | **Próximo Capítulo**: [Dicionários](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/10.Dicion%C3%A1rios.md) 241 | -------------------------------------------------------------------------------- /Capitulos/23.ExpressõesRegulares.md: -------------------------------------------------------------------------------- 1 | # Expressões Regulares 2 | 3 | **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**, 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*. 4 | 5 | ## Introdução básica 6 | 7 | #### Âncoras: **^** e **$** 8 | 9 | | Exemplo | Descrição | URL | 10 | |----------|------------------------------------------------|------------------------------------| 11 | | ^Py | encontra qualquer string que comece com Py | **https://regex101.com/r/cO8lqs/4303** | 12 | | on$ | encontra uma string que termina com on | **https://regex101.com/r/cO8lqs/4304** | 13 | | ^Python$ | encontra a string Python | **https://regex101.com/r/cO8lqs/4305** | 14 | | Python | encontra qualquer string que tenha Python em si | | 15 | 16 | #### Quantificadores: *, **+**, **?** e **{}** 17 | 18 | | Exemplo | Descrição | 19 | |------------|-------------------------------------------------------------------------------------| 20 | | abc* | encontra uma string que tenha ab seguido por zero ou mais c | 21 | | abc+ | encontra uma string que tenha ab seguido por um ou mais c | 22 | | abc? | encontra uma string que tenha ab seguido por zero, ou um c | 23 | | abc{2} | encontra uma string que tenha ab seguido por dois c | 24 | | abc{2,} | encontra uma string que tenha ab seguido por dois ou mais c | 25 | | abc{2,5} | encontra uma string que tenha ab seguido por 2 até no máximo 5 c | 26 | | a(bc)* | encontra uma string que tenha a seguido por zero ou mais cópias da sequência bc | 27 | | a(bc){2,5} | encontra uma string que tenha a seguido por 2 até no máximo 5 cópias da sequência bc | 28 | 29 | Veja e experimente mais opções: **https://regex101.com/r/cO8lqs/1** 30 | 31 | #### Operador OU: **|** e **[]** 32 | 33 | | Exemplo | Descrição | 34 | |---------|-----------------------------------------------------------------------------------| 35 | | a(b\|c) | encontra uma string que tenha a seguido por b ou c | 36 | | a[bc] | igual o anterior, ambas as notações podem ser usadas e produzem o mesmo resultado | 37 | 38 | #### Classes de caracteres: **\d**, **\w**, **\s** e **.** 39 | 40 | | Exemplo | Descrição | 41 | |---------|-------------------------------------------------------------------------| 42 | | \d | encontra um único caracter que seja um dígito | 43 | | \w | encontra um caracter de palavra (caracter alfanumérico e underline) | 44 | | \s | encontra caracteres de espaço em branco (incluindo tabs e quebra de linha) | 45 | | . | encontra qualquer caracter | 46 | 47 | #### Negação de classe de caracteres: **\D**, **\W**, **\S** 48 | 49 | | Exemplo | Descrição | 50 | |---------|-----------------------------------------------------------| 51 | | \D | Faz a operação inversa de \d e traz todos os não-dígitos | 52 | | \W | Faz a operação inversa de \w e traz todas as não-palavras | 53 | | \S | Faz a operação inversa de \s e traz todos os não-espaços | 54 | 55 | Outro ponto importante, é caso queiramos dar **escape**, por exemplo validar um **.**, para isso usamos o `\.` 56 | O mesmo vale caso seja necessário validarmos $, utilizamos `\$` 57 | 58 | ## Expressões Regulares em Python 59 | 60 | Python já possui incluído o módulo **re** que utilizaremos para nossas **expressões regulares**, para utilizá-lo é simples 61 | 62 | ```python 63 | import re 64 | 65 | # Vamos inspecionar o módulo para termos uma visão do que ele nos disponibiliza 66 | print(dir(re)) # ['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'] 67 | ``` 68 | 69 | Veja que temos bastantes opções, inicialmente vamos ver os métodos **findall()**, **split()**, **search()** e **match()** 70 | 71 | #### findall() 72 | 73 | ```python 74 | import re 75 | 76 | x = "Expressões regulares são legais" 77 | r = re.findall(r"\w+", x) 78 | print(r) # ['Expressões', 'regulares', 'são', 'legais'] 79 | ``` 80 | 81 | Como podemos ver, todos os caracteres da sentença obtiveram **match** e recebemos uma lista deles 82 | 83 | #### split() 84 | 85 | ```python 86 | import re 87 | 88 | e = "Eu sou uma expressao com diversas palavras" 89 | r = re.split(r'\s', e) 90 | print(r) # ['Eu', 'sou', 'uma', 'expressao', 'com', 'diversas', 'palavras'] 91 | ``` 92 | 93 | Como podemos ver, a função **split()** separou a expressao em diversos valores, usando o separador \s que representa espaço em branco 94 | 95 | #### search() 96 | 97 | ```python 98 | import re 99 | padrao = "a*b" 100 | r = re.search(padrao, "aaaaaaabcedefg") 101 | print(r) # <_sre.SRE_Match object; span=(0, 8), match='aaaaaaab'> 102 | print(r.group()) # aaaaaaab 103 | ``` 104 | 105 | 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 os métodos **start()**, **end()** e **span()**. 106 | 107 | #### match() 108 | 109 | ```python 110 | import re 111 | 112 | padrao = "\w+@(\w+\.)+(com|org|net)" # Padrao simples para darmos match em um email 113 | r = re.match(padrao, "teste@teste.org") 114 | print(r.group()) # teste@teste.org 115 | ``` 116 | 117 | 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 que devemos focar bastante, pois está presente em praticamente todas as linguagens de programação e sua aplicabilidade é muito vasta. 118 | 119 | **Próximo Capítulo**: [JSON](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/24.PythonJSON.md) 120 | -------------------------------------------------------------------------------- /Capitulos/07.Operadores.md: -------------------------------------------------------------------------------- 1 | # Operadores 2 | 3 | **Operadores** são **símbolos especiais** capazes de executar computação **aritmética** ou **lógica**. 4 | 5 | Existem diversos tipos de operadores em **Python**: 6 | 7 | - Operadores Aritméticos 8 | - Operadores de Atribuição 9 | - Operadores de Comparação 10 | - Operadores Lógicos 11 | - Operadores de Identidade 12 | - Operadores de Membros 13 | - Operadores Bitwise 14 | 15 | ## Operadores Aritméticos 16 | 17 | | Operador | Descrição | Exemplo | 18 | |----------|----------------------------------------------------------------------------|---------| 19 | | + | Adiciona dois operandos | 2+5 | 20 | | - | Subtrai o operando da direita pelo da esquerda | 7-2 | 21 | | * | Multiplica dois operandos | 3*3 | 22 | | / | Divide o operando da esquerda pelo da direita | 3/2 | 23 | | % | Módulo, resto da divisão do operando da esquerda pelo da direita | 10%3 | 24 | | // | Divisão arredondada, esta divisão retorna um número inteiro | 3//2 | 25 | | ** | Expoente, operando a esquerda elevado à potência do operando a direita | 2**32 | 26 | 27 | Por exemplo: 28 | 29 | ```python 30 | x = 10 31 | y = 6 32 | z = 6.0 33 | 34 | print("x + y = ", x+y) # Nos resulta 16 35 | print("x - y = ", x-y) # Nos resulta 4 36 | print("x * y = ", x*y) # Nos resulta 60 37 | print("x / y = ", x/y) # Nos resulta 1 38 | print("x / y = ", x/z) # Nos resulta 1.6666666666666667 39 | print("x // y = ", x//y) # Nos resulta 1 40 | print("x ** y = ", x**y) # Nos resulta 1000000 41 | ``` 42 | 43 | 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**. 44 | 45 | ## Operadores de Atribuição 46 | 47 | | Operador | Exemplo 1 | Exemplo 2 | 48 | |----------|-----------|------------| 49 | | = | x = 3 | x = 3 | 50 | | += | x += 3 | x = x + 3 | 51 | | -= | x -= 3 | x = x - 3 | 52 | | *= | x *= 3 | x = x * 3 | 53 | | /= | x /= 3 | x = x / 3 | 54 | | %= | x %= 3 | x = x % 3 | 55 | | //= | x //= 3 | x = x // 3 | 56 | | **= | x **= 3 | x = x ** 3 | 57 | | &= | x &= 3 | x = x & 3 | 58 | | \|= | x \|= 3 | x = x \| 3 | 59 | | ^= | x ^= 3 | x = x ^ 3 | 60 | | >>= | x >>= 3 | x = x >> 3 | 61 | | <<= | x <<= 3 | x = x << 3 | 62 | 63 | ## Operadores de Comparação 64 | 65 | Operadores de comparação são usados para comparar valores. Retornarão **True** ou **False** de acordo com a condição. 66 | 67 | | Operador | Descrição | Exemplo | 68 | |----------|--------------------------------------------------------------------------------------|---------| 69 | | > | Maior que - True se o operando a esquerda for maior que o da direita | x > y | 70 | | < | Menor que - True se o operando a esquerda for menor que o da direita | x < y | 71 | | == | Igual - True se ambos os operandos forem iguais | x == y | 72 | | != | Não Igual - True se os operandos forem diferentes | x != y | 73 | | >= | Maior que ou Igual - True se o operando da esquerda for maior ou igual ao da direita | x >= y | 74 | | <= | Menor que ou Igual - True se o operando da esquerda for menor ou igual ao da direita | x <= y | 75 | 76 | ```python 77 | x = 12 78 | y = 3 79 | 80 | print(x>y) # True 81 | print(x=y) # True 85 | print(x<=y) # False 86 | ``` 87 | 88 | ## Operadores Lógicos 89 | 90 | Operadores Lógicos são usados para combinar **comandos condicionais** 91 | 92 | | Operador | Descrição | Exemplo | 93 | |----------|-------------------------------------------------------------------------|------------------| 94 | | and | Retorna True se ambos os comandos são verdadeiros | x < y and x < 10 | 95 | | or | Retorna True se um dos comandos é verdadeiro | x < y or x > 3 | 96 | | not | Reverte o resultado, retorna False se o resultado for True e vice-versa | not(x > 10) | 97 | 98 | ## Operadores de Identidade 99 | 100 | **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!* 101 | 102 | | Operador | Descrição | 103 | |----------|----------------------------------------------------------------------| 104 | | is | True se os operandos são idênticos (referem ao mesmo objeto) | 105 | | is not | True se os operandos não são idênticos (não referem ao mesmo objeto) | 106 | 107 | ```python 108 | x = 1 109 | y = 1 110 | 111 | print(x is y) # True 112 | print(x is not y) # False 113 | ``` 114 | 115 | ```python 116 | a = "cachorro" 117 | b = "cachorro" 118 | 119 | print(a is b) # True 120 | print(a is not b) # False 121 | ``` 122 | 123 | ```python 124 | z = [1,2,3] 125 | k = [1,2,3] 126 | 127 | print(z is k) # False 128 | print(z is not k) # True 129 | ``` 130 | 131 | Perceba aqui que **x** e **y** são inteiros do mesmo valor, então eles são iguais e idênticos, o mesmo vale 132 | 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. 133 | 134 | ## Operadores de Membros 135 | 136 | | Operador | Descrição | Exemplo | 137 | |----------|-----------------------------------------------------------------|-------------------| 138 | | in | Retorna True se o valor/variável é encontrado na sequência | "c" in "cachorro" | 139 | | not in | Retorna True se o valor/variável não está presenta na sequência | 1 not in [1,2,3] | 140 | 141 | ```python 142 | a = [1,2,3] 143 | b = "Guilherme" 144 | 145 | print(1 in a) # Retorna True, pois 1 se encontra na lista a 146 | print("o" in b) # Retorna False, pois o não se encontra na string b 147 | ``` 148 | 149 | ## Operadores Bitwise 150 | 151 | Os operadores Bitwise atuam nos operandos como se eles fossem strings ou dígitos binários, eles 152 | executam operações **bit** por **bit**, por isso levam o nome **Bitwise**. 153 | 154 | Considere o valor 2 que é representado por 10 em binário e 7 que é representado por 111 155 | 156 | ```python 157 | x = 10 158 | y = 4 159 | 160 | # Vamos utilizar a função bin() que nos retorna uma string binária 161 | 162 | print(bin(x)) # 0b1010 163 | print(bin(y)) # 0b100 164 | ``` 165 | 166 | Adaptando-os, temos **(x = 0000 1010)** em binário e **(y = 0000 0100)** em binário, vamos aos operadores 167 | 168 | | Operador | Descrição | Exemplo | 169 | |----------|---------------------|-------------------------| 170 | | & | Bitwise AND | x & y = 0 (0000 0000) | 171 | | \| | Bitwise OR | x \| y = 14 (0000 1110) | 172 | | ~ | Bitwise NOT | ~x = -11 (1111 0101) | 173 | | ^ | Bitwise XOR | x ^ y = 14 (0000 1110) | 174 | | >> | Bitwise right shift | x >> 2 = 2 (0000 0010) | 175 | | << | Bitwise left shift | x << 2 = 40 (0010 1000) | 176 | 177 | Lembre sempre que os operadores tem um papel fundamental na programação e que devemos entender 178 | o seu funcionamento de maneira plena, *faça experimentos e divirta-se com os cálculos*! 179 | 180 | **Próximo Capítulo**: [Listas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/08.Listas.md) 181 | -------------------------------------------------------------------------------- /Capitulos/10.Dicionários.md: -------------------------------------------------------------------------------- 1 | # Dicionários 2 | 3 | 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. 4 | 5 | Eles são uma coleção **não-ordenada** de **chave-valor**, são normalmente usados quando temos uma grande quantidade de dados. Dicionários são otimizados para buscarmos dados e para isso, precisamos saber sua **chave**. Dicionários são definidos entre chaves **{}** onde cada item é um par na forma de **chave:valor**, sendo a chave e o valor podendo ser de qualquer tipo 6 | 7 | - **Valores** 8 | - qualquer tipo (**imutável e mutável**) 9 | - pode ser **duplicado** 10 | - valores de dicionários podem ser listas, até mesmo outros dicionários 11 | 12 | - **Chaves** 13 | - Devem ser **únicas** 14 | - tipo **imutável** (int, float, string, tuple, bool) 15 | - 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* 16 | - Tenha cuidado com o tipo *float* como chave 17 | - Nenhuma ordem para chaves ou valores 18 | 19 | ```python 20 | d = {'chave1':'valor1', 'chave2':'valor2'} 21 | print(d) # {'chave1': 'valor1', 'chave2': 'valor2'} 22 | print(type(d)) # 23 | ``` 24 | 25 | Também podemos escrever dessa forma, o que torna o dicionário mais legível 26 | 27 | ```python 28 | pessoa = { 29 | "nome" : "Gabriel", 30 | "idade" : 27, 31 | "profissao": "programador" 32 | } 33 | ``` 34 | 35 | --------------------------------------- 36 | 37 | ## Acessando e Manipulando Dados 38 | 39 | Para acessarmos os itens do dicionário, precisamos nos referir a sua chave 40 | 41 | ```python 42 | print(pessoa['nome']) # Gabriel 43 | ``` 44 | 45 | Podemos utilizar o método get() também 46 | 47 | ```python 48 | print(pessoa.get('nome')) # Gabriel 49 | ``` 50 | 51 | É possível alterar os valores de um dicionário 52 | 53 | ```python 54 | pessoa['idade'] = 28 55 | print(pessoa['idade']) # 28 56 | ``` 57 | 58 | --------------------------------------- 59 | 60 | ### Percorrendo os valores de um Dicionário 61 | 62 | ```python 63 | personagem = { 64 | "nome" : "Talantyr", 65 | "classe" : "mago", 66 | "vida" : 100 67 | } 68 | 69 | for d in personagem: # Percorre os valores do dicionário 70 | print(personagem[d]) # Imprime os valores do dicionário 71 | ``` 72 | 73 | --------------------------------------- 74 | 75 | ### Também podemos usar a função values() 76 | 77 | ```python 78 | for d in personagem.values(): # Percorre os valores do dicionário 79 | print(d) # Imprime os valores do dicionário 80 | ``` 81 | 82 | Além disso é possível percorrer tanto as chaves como os valores, usando a função items() 83 | 84 | ```python 85 | for chave,valor in personagem.items(): # Percorre as chaves e os valores 86 | print(chave,valor) # Imprime as chaves e os valores 87 | ``` 88 | 89 | Caso seja necessário verificar a presença de uma chave no dicionário, podemos 90 | 91 | ```python 92 | print('nome' in personagem) # True 93 | ``` 94 | 95 | Assim como nas listas e tuplas, também podemos aplicar o método len() nos dicionários 96 | 97 | ```python 98 | print(len(personagem)) # 3 99 | ``` 100 | 101 | --------------------------------------- 102 | 103 | ### Adicionando Itens ao Dicionário 104 | 105 | Para adicionarmos um novo item em nosso dicionário usamos uma nova chave e atribuimos um valor a ela 106 | 107 | ```python 108 | personagem['altura'] = 1.75 109 | print(personagem) 110 | ``` 111 | 112 | --------------------------------------- 113 | 114 | ### Removendo Itens do Dicionário 115 | 116 | Podemos também, de várias formas, remover os itens do dicionário 117 | 118 | Método **pop()** 119 | 120 | ```python 121 | personagem.pop('altura') 122 | print(personagem) 123 | ``` 124 | 125 | Método **popitem()** 126 | 127 | ```python 128 | personagem.popitem() 129 | print(personagem) 130 | ``` 131 | 132 | --------------------------------------- 133 | 134 | ### del 135 | 136 | A palavra-chave **del** remove um item com a chave especificada 137 | 138 | ```python 139 | dicionario = {'k1': "a", 'k2': "b"} 140 | del dicionario['k1'] 141 | print(dicionario) # {'k2': 'b'} 142 | ``` 143 | 144 | Além disso é possível (**atenção**) deletar o dicionário por completo 145 | 146 | ```python 147 | del dicionario 148 | ``` 149 | 150 | ### Construtor dict() 151 | 152 | O construtor **dict()** nos permite também criar dicionários 153 | 154 | ```python 155 | dict = dict(nome="Pedro", idade=19) 156 | print(dict) 157 | ``` 158 | 159 | ### Método clear() 160 | 161 | O método **clear()** nos permite esvaziar o dicionário 162 | 163 | ```python 164 | dict.clear() 165 | print(dict) 166 | ``` 167 | 168 | --------------------------------------- 169 | 170 | ## Ordenando um Dicionário 171 | 172 | Vamos criar um dicionário chamado `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)** 173 | 174 | Criando o Dicionário 175 | 176 | ```python 177 | pokedex = [ 178 | {'nome':'pikachu','tipo':'elétrico'}, 179 | {'nome':'charizard','tipo':'fogo'}, 180 | {'nome':'bulbasaur','tipo':'planta'}, 181 | {'nome':'squirtle','tipo':'aquatico'} 182 | ] 183 | ``` 184 | 185 | Ordenando os pokémons por **tipo** através de uma expressão lambda 186 | 187 | ```python 188 | ordenados = sorted(pokedex, key=lambda x: x['tipo']) 189 | print(ordenados) 190 | # [{'nome': 'squirtle', 'tipo': 'aquatico'}, {'nome': 'pikachu', 'tipo': 'elétrico'}, {'nome': 'charizard', 'tipo': 'fogo'}, {'nome': 'bulbasaur', 'tipo': 'planta'}] 191 | ``` 192 | 193 | --------------------------------------- 194 | 195 | ## Dicionários Comprehesions 196 | 197 | 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. 198 | 199 | ```python 200 | # Iniciando nossas listas 201 | autores = ['Aldous Huxley','George Orwell','Ray Bradbury','William Gibson'] 202 | livros = ['Brave New World','1984','Fahrenheit 451','Neuromancer'] 203 | 204 | # Construindo um dicionário 205 | autores_livros = {autor: livro for autor, livro in zip(autores, livros)} 206 | print(autores_livros) 207 | # {'Aldous Huxley': 'Brave New World', 'George Orwell': '1984', 'Ray Bradbury': 'Fahrenheit 451', 'William Gibson': 'Neuromancer'} 208 | ``` 209 | 210 | --------------------------------------- 211 | 212 | ## Dicionários Aninhados 213 | 214 | 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: 215 | 216 | ```python 217 | jogos = { 218 | '1':{'nome':'castlevania','genero':'aventura'}, 219 | '2':{'nome':'super mario','genero':'aventura'}, 220 | '3':{'nome':'world of warcraft','genero':'MMORPG'} 221 | } 222 | 223 | print(jogos['2']) # {'nome': 'super mario', 'genero': 'aventura'} 224 | print(jogos.get('1')) # {'nome': 'castlevania', 'genero': 'aventura'} 225 | ``` 226 | 227 | --------------------------------------- 228 | 229 | ## Fibonacci com Dicionários 230 | 231 | 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**. 232 | 233 | ```python 234 | def fib_eficiente(n, d): 235 | if n in d: 236 | return d[n] 237 | else: 238 | ans = fib_eficiente(n-1, d) + fib_eficiente(n-2, d) 239 | d[n] = ans 240 | return ans 241 | 242 | d = {1:1, 2:2} 243 | print(fib_eficiente(7, d)) # 21 244 | ``` 245 | 246 | --------------------------------------- 247 | 248 | 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. 249 | 250 | **Próximo Capítulo**: [Sets](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/11.Sets.md) 251 | -------------------------------------------------------------------------------- /Capitulos/24.PythonJSON.md: -------------------------------------------------------------------------------- 1 | # JSON 2 | 3 | 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*. Vale lembrarmos, que embora JSON carregue Javascript no seu nome, ele é independente e vale para qualquer linguagem de programação. 4 | 5 | Para entendermos melhor o **JSON**, vamos criar um arquivo `pessoa.json` que descreverá uma pessoa: 6 | 7 | ```javascript 8 | { 9 | "primeiroName": "Miguel", 10 | "segundoName": "Arcanjo", 11 | "estaVivo": true, 12 | "idade": 27, 13 | "endereço": { 14 | "rua": "Rua Alfa 33", 15 | "cidade": "São Paulo", 16 | "estado": "SP", 17 | "codigoPostal": "1321-32423" 18 | }, 19 | "numerosTelefones": [ 20 | { 21 | "tipo": "casa", 22 | "numero": "212 555-1234" 23 | }, 24 | { 25 | "tipo": "escritorio", 26 | "numero": "646 555-4567" 27 | }, 28 | { 29 | "tipo": "celular", 30 | "numero": "123 456-7890" 31 | } 32 | ], 33 | "criancas": [], 34 | "esposa": null 35 | } 36 | ``` 37 | 38 | 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**, dentro de pessoa temos um objeto **endereço** e também temos um array de objetos chamado **numerosTelefones**. 39 | 40 | Para utilizarmos **JSON** em **Python**, contamos com o módulo **json**, que podemos importá-lo facilmente: 41 | 42 | ```python 43 | import json 44 | ``` 45 | 46 | --------------------------------------- 47 | 48 | ## Parse de JSON, convertendo JSON para Python 49 | 50 | 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. Por exemplo: 51 | 52 | ```python 53 | import json 54 | 55 | # Veja que além do arquivo .json, também podemos ter JSON armazenado como uma string 56 | x = '{ "nome":"Rafael", "idade":29, "cidade":"São Paulo"}' 57 | 58 | # Fazendo o parse 59 | y = json.loads(x) 60 | print(y['idade']) # 29 61 | ``` 62 | 63 | --------------------------------------- 64 | 65 | ## Convertendo Python para JSON 66 | 67 | Se quisermos, também podemos converter um objeto de Python em uma string JSON, para isso vamos usar o método **json.dumps()** 68 | 69 | ```python 70 | import json 71 | 72 | # Dicionário Python 73 | d = { 74 | "nome": "Gabriel", 75 | "idade": 27, 76 | "cidade": "Curitiba" 77 | } 78 | 79 | j = json.dumps(d) # Converte para JSON 80 | print(j) # {"nome": "Gabriel", "idade": 27, "cidade": "Curitiba"} 81 | ``` 82 | 83 | É 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 84 | 85 | | Python | JSON | 86 | |--------|--------| 87 | | dict | Object | 88 | | list | Array | 89 | | tuple | Array | 90 | | str | String | 91 | | int | Number | 92 | | float | Number | 93 | | True | true | 94 | | False | false | 95 | | None | null | 96 | 97 | --------------------------------------- 98 | 99 | ## Veja um exemplo com todos os tipos de dados 100 | 101 | ```python 102 | import json 103 | 104 | personagem = { 105 | "nome": "Talantyr", 106 | "epiteto": "O Glorioso", 107 | "nível": 45, 108 | "vivo": True, 109 | "atributos": {"força": 45, "destreza": 60, "inteligência": 70}, 110 | "mascotes": ("Lobo","Coruja"), 111 | "magias": None, 112 | "itens": [ 113 | {"nome": "poção de mana", "quantidade": 5}, 114 | {"nome": "poção de vida", "quantidade": 7} 115 | ] 116 | } 117 | 118 | print(json.dumps(personagem, ensure_ascii=False)) 119 | # {"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}]} 120 | ``` 121 | 122 | --------------------------------------- 123 | 124 | ## Para obtermos um output mais limpo: 125 | 126 | ```python 127 | print(json.dumps(personagem, ensure_ascii=False, indent=4)) 128 | ``` 129 | 130 | ### Veja que obtivemos: 131 | 132 | ```javascript 133 | { 134 | "nome": "Talantyr", 135 | "epiteto": "O Glorioso", 136 | "nível": 45, 137 | "vivo": true, 138 | "atributos": { 139 | "força": 45, 140 | "destreza": 60, 141 | "inteligência": 70 142 | }, 143 | "mascotes": [ 144 | "Lobo", 145 | "Coruja" 146 | ], 147 | "magias": null, 148 | "itens": [ 149 | { 150 | "nome": "poção de mana", 151 | "quantidade": 5 152 | }, 153 | { 154 | "nome": "poção de vida", 155 | "quantidade": 7 156 | } 157 | ] 158 | } 159 | ``` 160 | 161 | ### Caso queiramos o resultado organizado, podemos usar o parâmetro sort_keys 162 | 163 | ```python 164 | print(json.dumps(p, indent = 4, sort_keys = True)) 165 | ``` 166 | 167 | ### Veja nosso resultado: 168 | 169 | ```javascript 170 | { 171 | "atributos": { 172 | "destreza": 60, 173 | "força": 45, 174 | "inteligência": 70 175 | }, 176 | "epiteto": "O Glorioso", 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 | "magias": null, 188 | "mascotes": [ 189 | "Lobo", 190 | "Coruja" 191 | ], 192 | "nome": "Talantyr", 193 | "nível": 45, 194 | "vivo": true 195 | } 196 | ``` 197 | 198 | --------------------------------------- 199 | 200 | ## Utilizando uma API 201 | 202 | 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. 203 | 204 | ```python 205 | import json 206 | import requests 207 | 208 | r = requests.get('https://jsonplaceholder.typicode.com/posts') 209 | posts = r.json() 210 | 211 | for post in posts: 212 | print(post) # Imprime todos os posts 213 | print(post['id']) # Imprime todos os ids 214 | print(post['title']) # Imprime todos os títulos 215 | print(post['body']) # Imprime todos os textos 216 | ``` 217 | 218 | Como podemos observar, conseguimos obter os dados com sucesso e agora podemos trabalhar com eles da forma que desejarmos. 219 | 220 | --------------------------------------- 221 | 222 | ## JSONPickle 223 | 224 | A biblioteca **[jsonpickle](https://jsonpickle.github.io/)** nos permite **serializar** e **deserializar** objetos complexos em Python para JSON e também de JSON. Vejamos exemplos para ilustrar: 225 | 226 | Vamos criar um objeto `Gato` 227 | 228 | ```python 229 | class Gato: 230 | def __init__(self, nome, raca): 231 | self.nome = nome 232 | self.raca = raca 233 | ``` 234 | 235 | Agora vamos criar um novo `Gato` 236 | 237 | ```python 238 | gato = Gato('Osíris','Sphynx') 239 | ``` 240 | 241 | Transformando o objeto `Gato` em uma string JSON e salvando em um arquivo 242 | 243 | ```python 244 | import jsonpickle 245 | 246 | with open('gato.json', 'w') as file: 247 | frozen = jsonpickle.encode(gato) 248 | file.write(frozen) 249 | ``` 250 | 251 | Lendo o arquivo JSON e decodificando para recriar o objeto `Gato` 252 | 253 | ```python 254 | with open('gato.json', 'r') as file: 255 | contents = file.read() 256 | unfrozen = jsonpickle.decode(contents) 257 | print(unfrozen) # <__main__.Gato object at 0x7efdfeeca5c0> 258 | print(unfrozen.raca) # Sphynx 259 | ``` 260 | 261 | --------------------------------------- 262 | 263 | 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. 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)** 264 | 265 | **Próximo Capítulo**: [XML](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/25.PythonXML.md) 266 | -------------------------------------------------------------------------------- /Capitulos/29.PIP.md: -------------------------------------------------------------------------------- 1 | # PIP 2 | 3 | **PIP** é o *gerenciador de pacotes do Python*, também conhecidos como **módulos** / **bibliotecas**. 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. Para confirmar, vamos digitar no nossa **interface de linha de comando** 4 | 5 | ``` 6 | pip --version 7 | ``` 8 | 9 | Caso ele não esteja presente em sua máquina, você pode encontrá-lo em **https://pypi.org/project/pip/** 10 | 11 | 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/** 12 | 13 | --------------------------------------- 14 | 15 | ## Mas e o que são os Pacotes? 16 | 17 | 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. 18 | 19 | --------------------------------------- 20 | 21 | ## Instalando pacotes 22 | 23 | Novamente, vamos abrir nossa **interface de linha de comando** e vamos até o diretório que está nosso script: 24 | 25 | ```python 26 | pip install requests 27 | ``` 28 | 29 | Será iniciado um processo de *download e instalação*, aguarde um pouco e estará pronto, agora poderemos usar a nova biblioteca. 30 | 31 | --------------------------------------- 32 | 33 | ## Utilizando o Pacote 34 | 35 | ```python 36 | import requests 37 | 38 | print(dir(requests)) 39 | # ['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'] 40 | 41 | r = requests.get("http://google.com") 42 | print(r.status_code) 43 | print(r.text) 44 | print(r.encoding) 45 | ``` 46 | 47 | 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. 48 | 49 | --------------------------------------- 50 | 51 | ## Removendo um Pacote 52 | 53 | Para desinstalarmos um pacote de nossa máquina podemos usar o comando `uninstall` 54 | 55 | ``` 56 | pip uninstall requests 57 | ``` 58 | 59 | É necessário confirmarmos a desinstalação com a tecla `y` 60 | 61 | --------------------------------------- 62 | 63 | ## Listando os Pacotes 64 | 65 | Podemos usar o comando `list` para listarmos os pacotes que temos instalado em nossa máquina 66 | 67 | ``` 68 | pip list 69 | ``` 70 | 71 | --------------------------------------- 72 | 73 | ## Atualizando um Pacote Existente 74 | 75 | O comando `install --upgrade` nos permite atualizar um pacote para sua versão mais recente 76 | 77 | ``` 78 | pip install --upgrade requests 79 | ``` 80 | 81 | --------------------------------------- 82 | 83 | ## Obtendo Informações 84 | 85 | Através do comando `show` podemos obter informações sobre um determinado pacote 86 | 87 | ``` 88 | pip show requests 89 | ``` 90 | 91 | Podemos também fazer pesquisas por **palavras-chave** 92 | 93 | ``` 94 | pip search http 95 | ``` 96 | 97 | --------------------------------------- 98 | 99 | # Ambientes Virtuais 100 | 101 | 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. 102 | 103 | Para saber mais detalhes sobre os **Ambientes Virtuais** você pode visitar: **[venv](https://docs.python.org/3/library/venv.html)** 104 | 105 | --------------------------------------- 106 | 107 | ## Usando Ambientes Virtuais 108 | 109 | Antes de tudo, devemos instalar a ferramenta `virtualenv` que nos permite trabalhar com ambientes virtuais. 110 | 111 | ``` 112 | pip install virtualenv 113 | ``` 114 | 115 | 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 116 | 117 | ``` 118 | # Para Python 2 119 | virtualenv env 120 | 121 | # Para Python 3 122 | python3 -m venv env 123 | ``` 124 | 125 | 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: 126 | 127 | ``` 128 | ├── bin 129 | │ ├── activate 130 | │ ├── activate.csh 131 | │ ├── activate.fish 132 | │ ├── easy_install 133 | │ ├── easy_install-3.5 134 | │ ├── pip 135 | │ ├── pip3 136 | │ ├── pip3.5 137 | │ ├── python -> python3.5 138 | │ ├── python3 -> python3.5 139 | │ └── python3.5 -> /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 140 | ├── include 141 | ├── lib 142 | │ └── python3.5 143 | │ └── site-packages 144 | └── pyvenv.cfg 145 | ``` 146 | 147 | Cada *folder* no diretório `env` contém: 148 | 149 | - **bin**: arquivos que interagem com o ambiente virtual 150 | - **include**: Cabeçalhos **C** que compilam os pacotes Python 151 | - **lib**: Uma cópia da versão Python juntamente com o *folder* `site-packages` onde cada dependência está localizada 152 | 153 | --------------------------------------- 154 | 155 | ## Ativando um Ambiente Virtual 156 | 157 | 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`. 158 | 159 | De forma a usarmos os pacotes e recursos de um **ambiente virtual** é necessário que ativemos ele: 160 | 161 | ``` 162 | source env/bin/activate 163 | ``` 164 | 165 | Ou até mesmo utilizando somente `.` 166 | 167 | ``` 168 | . env/bin/activate 169 | ``` 170 | 171 | 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: 172 | 173 | ```python 174 | deactivate 175 | ``` 176 | 177 | Agora que vimos como **ativar** / **desativar** nosso ambiente, vamos reativá-lo e testá-lo instalando um biblioteca 178 | 179 | ```python 180 | pip install bcrypt 181 | ``` 182 | 183 | Abra o **Python Interactivo** ou um **Script** e vamos testar se a biblioteca está instalada corretamenta 184 | 185 | ```python 186 | import bcrypt 187 | 188 | bcrypt.hashpw('senha'.encode('utf-8'), bcrypt.gensalt(12)) 189 | # b'$2b$12$ZT52zrACwPVFy1ST8UbsKuRQ/LZmhMvmMB7EqchU1VUQTLTi4X7Mu' 190 | ``` 191 | 192 | --------------------------------------- 193 | 194 | ## Gerando o Arquivo requirements.txt 195 | 196 | 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. 197 | 198 | É 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` 199 | 200 | Assumindo que estamos em nosso **ambiente virtual** e temos a biblioteca **bcrypt** instalada, vamos executar: 201 | 202 | ```python 203 | pip freeze > requirements.txt 204 | ``` 205 | 206 | Ao verificar o contéudo do arquivo **requirements.txt**, encontramos o seguinte: 207 | 208 | ``` 209 | bcrypt==3.1.7 210 | cffi==1.12.3 211 | pycparser==2.19 212 | six==1.12.0 213 | ``` 214 | 215 | Caso queiramos instalar todos os pacotes contidos nele podemos usar o comando: 216 | 217 | ```python 218 | pip install -r requirements.txt 219 | ``` 220 | 221 | --------------------------------------- 222 | 223 | ## conda & pipenv 224 | 225 | Além do **pip** e do **ambiente virtual** tradicional que utilizamos anteriormente, também existem outras opções de gerenciadores de pacotes para Python 226 | 227 | - **conda**: https://docs.conda.io/en/latest/ 228 | - **pipenv**: https://docs.pipenv.org/en/latest/ 229 | 230 | **Próximo Capítulo**: [Python MySQL](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/30.PythonMySQL.md) 231 | -------------------------------------------------------------------------------- /Capitulos/06.Strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | --------------------------------------- 4 | 5 | ## Introdução 6 | 7 | **Definição**: Uma **[String](https://en.wikipedia.org/wiki/String_(computer_science))** é tradicionalmente um tipo de dados que representa uma sequência de caracteres. 8 | 9 | Caracteres podem ser **letras**, **dígitos**, **símbolos** ($, !, #, @), etc. 10 | 11 | Existem diversos problemas no mundo real que envolvem as **strings**, podemos citar: 12 | 13 | - Criptografia e Descriptografia 14 | - Análises de DNA 15 | - Tradução de linguagens 16 | 17 | Além dos números, **Python** é capaz de manipular **strings** com maestria, as strings podem ser expressas de diversas maneiras, podemos encapsular elas com aspas simples **('...')** ou também aspas duplas **("...")** ou até mesmo **("""...""")** para múltiplas linhas. Por exemplo: 18 | 19 | ```python 20 | print('String é um elemento importante da programação') 21 | print("Também podemos representá-las com aspas duplas") 22 | print("""Podemos, até mesmo, representá-las com três aspas duplas, para textos grandes""") 23 | ``` 24 | 25 | Como podemos ver, **strings** podem ser impressas utilizando a função **print()** 26 | Caso você queira usar palavras entre aspas na sua **string**, você deve usar \ **(contrabarra)** para dar *escape* nas aspas, caso contrário ocorrerá um erro: 27 | 28 | ```python 29 | print("Podemos usar aspas dentro das \"strings\"") 30 | print('Podemos usar aspas dentro das \'strings\'') 31 | ``` 32 | 33 | Ou até mesmo você pode **inverter** o uso das aspas: 34 | 35 | ```python 36 | print("Dessa forma não há 'problema'") 37 | print('Dessa forma não há "problema"') 38 | ``` 39 | 40 | --------------------------------------- 41 | 42 | ## Índices de Strings 43 | 44 | Assim como em diversas linguagens de programação, **strings** em **Python** são consideradas **arrays de bytes** que representam caractéres unicode, entretanto **Python** não tem um tipo de dados caracter. Caracteres únicos são simplesmente **strings** de tamanho 1. Para acessarmos elementos individuais das **strings**, utilizamos colchetes **[]**. 45 | 46 | ![img](https://i.imgur.com/uQokjlm.png) 47 | 48 | ```python 49 | s = "Rafael" 50 | print(s[0]) # Imprime a primeira letra do nome 51 | print(s[-6]) # Imprime a primeira letra do nome 52 | 53 | print(s[5]) # Imprime a última letra do nome 54 | print(s[-1]) # Imprime a última letra do nome 55 | ``` 56 | 57 | Notamos que foi utilizado a notação **nome[0]**, isso porque o primeiro caracter começa na posição 0, lembre que isso é muito comum nas linguagens de programação e estruturas de dados. Cada caracter na **string** é associado com um **índice** numérico, que é um inteiro representando a localização do caracter em uma determinada **string**. 58 | 59 | Além disso, podemos formar **substrings** a partir de uma **string**. 60 | 61 | ```python 62 | nome = "John Von Neumann" 63 | print(nome[6:11]) # Nesse caso, pegamos o caracter da posição 6 até 11(não incluindo) 64 | print(nome[-1]) # Caso queiramos, podemos pegar o último caracter utilizando números negativos 65 | print[nome[-2]) # Penúltimo caracter 66 | ``` 67 | 68 | --------------------------------------- 69 | 70 | ## Métodos em Strings 71 | 72 | Um detalhe importante dentro do universo das **strings** é que podemos utilizar **[métodos](https://www.w3schools.com/python/python_ref_string.asp)** (funções especiais) para manipulalá-las. 73 | 74 | ```python 75 | nome = " Meu nome é Dennis Ritchie " 76 | print(nome.strip()) # O método strip() remove todos os espaços no começo e no fim da string 77 | print(nome.len()) # O método len() retorna o tamanho da string 78 | print(nome.lower()) # O método lower() retorna a string em lower case 79 | print(nome.upper()) # O método upper() retorna a string em upper case 80 | print(nome.replace("Dennis", "Alan")) # O método replace substitui a string com outra string 81 | print(nome.split(" ")) # O método split separa a string em substrings caso haja um separador, nesse caso utilizamos o espaço (" ") e ele nos retorna uma lista de strings 82 | ``` 83 | 84 | --------------------------------------- 85 | 86 | ## Format String 87 | 88 | O método **format** nos permite construir **strings** de uma maneira flexível 89 | 90 | ```python 91 | nome = "Rafael" 92 | profissao = "Programador" 93 | 94 | print("A profissao de {0} é {1}".format(nome,profissao)) 95 | # A profissao de Rafael é Programador 96 | ``` 97 | 98 | Criando um elemento [HTML](https://www.w3schools.com/html/html_intro.asp) 99 | 100 | ```python 101 | tag = 'p' 102 | texto = 'Este é um parágrafo' 103 | 104 | sentenca = '<{0}>{1}'.format(tag, texto) 105 | print(sentenca) #

Este é um parágrafo

106 | ``` 107 | 108 | Calculando um valor 109 | 110 | ```python 111 | sentenca = '1 GB é igual a {:,} bytes'.format(10**9) 112 | print(sentenca) # 1 GB é igual a 1,000,000,000 bytes 113 | ``` 114 | 115 | Códigos de Formatação 116 | 117 | ```python 118 | # int 119 | print("{:d}".format(4)) 120 | # 4 121 | 122 | # binário 123 | print("{:b}".format(55)) 124 | # 110111 125 | 126 | # hex 127 | print("{:x}".format(15)) 128 | # f 129 | 130 | # lista 131 | print("{:}".format([20, 30])) 132 | # [20, 30] 133 | ``` 134 | 135 | Também podemos representar as **strings** de maneira similar à linguagem **C**: 136 | 137 | ```python 138 | # string 139 | nome = "Alan" 140 | amigo = "John" 141 | 142 | print("%s é amigo de %s" %(nome,amigo)) 143 | 144 | # int 145 | print("%d" % (4545)) 146 | 147 | # float 148 | print("%3.5f" % (3.123456789)) 149 | print("%2.4f" % (3.123456789)) 150 | ``` 151 | 152 | --------------------------------------- 153 | 154 | ### F-strings 155 | 156 | F-strings são um novo tipo de *string literals* introduzido na versão **[3.6](https://docs.python.org/3/whatsnew/3.6.html)** do Python. A **string** formatada é prefixada com `'f'` e é similar à formatação de strings aceita por `str.format()`. 157 | 158 | Vejamos exemplos: 159 | 160 | ```python 161 | first_name = "Alan" 162 | last_name = "Turing" 163 | 164 | # Podemos também executar métodos com F-Strings 165 | sentenca = f'Meu nome e {first_name.upper()} {last_name.lower()}' 166 | print(sentenca) # Meu nome e ALAN turing 167 | ``` 168 | 169 | Podemos também utilizar **dicionários** 170 | 171 | ```python 172 | pessoa = {'nome': 'Muhammad', 'idade': 22} 173 | 174 | sentenca = f'Meu nome é {pessoa["nome"]} e eu tenho {pessoa["idade"]} anos de idade' 175 | 176 | print(sentenca) 177 | ``` 178 | 179 | Ou até mesmo realizar operações matemáticas 180 | 181 | ```python 182 | calculo = f'4 vezes 11 é igual a {4 * 11}' 183 | print(calculo) 184 | 185 | for n in range(1,11): 186 | sentenca = f'O Valor é {n:02}' 187 | print(sentenca) 188 | ``` 189 | 190 | Para formatarmos datas precisaremos importar a biblioteca **datetime** 191 | 192 | ```python 193 | from datetime import datetime 194 | 195 | nascimento = datetime(1991, 6, 6) 196 | 197 | sentenca = f'O Nascimento é no dia {nascimento:%B %d, %Y}' 198 | 199 | print(sentenca) 200 | ``` 201 | 202 | --------------------------------------- 203 | 204 | ## Convertendo para o formato String 205 | 206 | Para fazermos a conversão para uma string podemos utilizar os métodos `repr()` e `str()` 207 | 208 | ```python 209 | x = 10 210 | y = [1, 3.14, 17, 13] 211 | 212 | print(repr(x)) 213 | print(str(y)) 214 | ``` 215 | 216 | **Strings** também são capazes de aceitar **Escape caracteres** 217 | 218 | | Carácter | Descrição | 219 | |---------|-----------------| 220 | | \n | nova linha | 221 | | \r | carriage return | 222 | | \s | espaço | 223 | | \t | tab | 224 | | \v | tab vertical | 225 | | \e | escape | 226 | | \b | backspace | 227 | 228 | ```python 229 | print("Meu nome é\nGabriel") 230 | print("\tOlá meu amigo") 231 | ``` 232 | 233 | Operadores Especiais 234 | 235 | | Operador | Descrição | 236 | |----------|----------------------------------------------------------------| 237 | | + | concatenação, adiciona os valores | 238 | | * | repetição, concatena múltiplas cópias da mesma string | 239 | | in | para verificarmos se determinado caracter existe na string | 240 | | not in | para verificarmos se determinado caracter não existe na string | 241 | 242 | Veja um exemplo dos Operadores Especiais 243 | 244 | ```python 245 | nome = "Carl" 246 | sobrenome = "Sagan" 247 | 248 | print(nome +" "+ sobrenome) # Concatena o nome e sobrenome 249 | print(nome*10) # Multiplica o nome por 10 250 | print("C" in nome) # Verifica se C está presente em nome e retorna True 251 | print("C" not in nome) # Verifica se C não está presente em nome e retorna False 252 | ``` 253 | 254 | É importante lembrarmos que **strings** são imutáveis, uma vez criada, não pode ser modificada. Para alterar uma **string** você deve primeiro construir uma nova string através da concatenação ou chamada de uma função e então re-atribuir à variável **string**. 255 | 256 | O conteúdo de **strings** é bastante extenso e continuaremos vendo elas ao longo do guia, considere dar bastante importância a elas! 257 | 258 | **Próximo Capítulo**: [Operadores](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/07.Operadores.md) 259 | -------------------------------------------------------------------------------- /Capitulos/01.Introdução.md: -------------------------------------------------------------------------------- 1 | # Introdução 2 | 3 | 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 4 | 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)**. 5 | 6 | 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. 7 | 8 | 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/)** 9 | 10 | --------------------------------------- 11 | 12 | ## As principais aplicações de Python são: 13 | 14 | - Desenvolvimento web **[(lado do servidor)](https://pt.wikipedia.org/wiki/Server-side)** 15 | - Desenvolvimento de softwares em geral 16 | - Matemática e Computação Científica 17 | - Inteligência Artificial, **[Machine Learning](https://en.wikipedia.org/wiki/Machine_learning)**, **[Deep Learning](https://en.wikipedia.org/wiki/Deep_learning)** 18 | - **[Scripting](https://pt.wikipedia.org/wiki/Linguagem_de_script)** e automação de tarefas repetitivas 19 | - Testes de software 20 | 21 | --------------------------------------- 22 | 23 | ## Por que aprender Python? 24 | 25 | - Python é capaz de rodar em múltiplas plataformas (**Windows**, **Linux**, **MacOS**, **Raspberry Pi**, etc) 26 | - Python suporta **programação interativa** (Interação direta com o interpretador) 27 | - Sua sintaxe é simples de compreender 28 | - Suporta múltiplos **[paradigmas de programação](https://pt.wikipedia.org/wiki/Paradigma_de_programação)** 29 | - Python pode ser usada para prototipação rápida 30 | - 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 31 | - Pode ser utilizada para lidar com grandes quantidades de dados e executar cálculos matemáticos complexos 32 | - Python conta com uma comunidade gigantesca e muito material de aprendizado! 33 | 34 | --------------------------------------- 35 | 36 | ## Importante 37 | 38 | - 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 atualmente só esteja recebendo atualizações de segurança 39 | - Python pode ser integrada com **C**, **C++**, **CORBA**, **Java**. Caso haja a necessidade de trabalhar com códigos de alta perfomance 40 | - Atualmente muitas das grandes corporações utilizam Python, podemos citar elas: **Google**, **Facebook**, **Microsoft**, **NASA**, **CERN**. 41 | 42 | --------------------------------------- 43 | 44 | # Computação 45 | 46 | ![img](https://media2.giphy.com/media/8YBpKSm3uPWG9Ca0F4/giphy.gif) 47 | 48 | Uma breve Introdução à Computação 49 | 50 | ## O que seria? 51 | 52 | - Representação de conhecimento através de **Estruturas de Dados** 53 | - **Iteração** e **Recursão** como metáforas computacionais 54 | - **Abstração** de procedimentos e tipos de dados 55 | - **Organizar** e **Modularizar** sistemas utilizando objetos classes e métodos 56 | - Diferentes classes de **algoritmos** (searching, sorting) 57 | - **Complexidade** de algoritmos 58 | 59 | ## O que um Computador faz? 60 | 61 | - Fundamentalmente 62 | - Realiza cálculos (bilhões de cálculos por segundo) 63 | - É capaz de lembrar resultados (centenas de gigabytes de storage) 64 | 65 | - Quais tipos de cálculos? 66 | - Pré-construídos na linguagem 67 | - Aqueles que você define como programador 68 | 69 | - **Computadores** apenas sabem o que dizemos a eles 70 | 71 | ## Tipos de Conhecimento 72 | 73 | - **Conhecimento Declarativo** é uma afirmação de um fato 74 | - Está chovendo lá fora 75 | 76 | - **Conhecimento Imperativo** é uma **receita** ou "tutorial" 77 | - Gabriel se inscreve para um sorteio 78 | - Gabriel começa a pensar 79 | - Gabriel escolhe um número aleatório entre 1 e 10 80 | - Gabriel acerta o número 81 | 82 | ## Exemplo Numérico 83 | 84 | - A raiz quadrada de um número **x** é **y** de forma que `y*y = x` 85 | 86 | - Receita para deduzir a raiz quadrada de um número **x** 87 | 88 | 1. Comece com uma suposição **g** 89 | 2. Se `g*g` é próximo o suficiente de **x**, pare e diga que **g** é a resposta 90 | 3. Caso contrário faça uma nova suposição calculando a média de **g** e **x/g** 91 | 4. Utilizando a nova suposição, repita o processo até se aproximar 92 | 93 | | g | g*g | x/g | (g+x/g)/2 | 94 | |--------|---------|-------|-----------| 95 | | 3 | 9 | 16/3 | 4.17 | 96 | | 4.17 | 17.36 | 3.837 | 4.0035 | 97 | | 4.0035 | 16.0277 | 3.997 | 4.000002 | 98 | 99 | ## O que é uma Receita? 100 | 101 | - Uma sequência de simples passos 102 | - Processo de **Controle de fluxo** que específica quando cada passo é executado 103 | - Um meio de determinar quando parar 104 | 105 | 1+5+7 = UM **ALGORITMO**! 106 | 107 | ## Computadores são Máquinas 108 | 109 | - Como capturar uma receita em um processo mecânico 110 | 111 | - Computador de **Programa Fixo** 112 | - Calculadora 113 | 114 | - Computador de **Programa Armazenado** 115 | - Máquina armazena e executa instruções 116 | 117 | ## Arquitetura Básica do Computador 118 | 119 | ![img](https://i.imgur.com/btawhB6.png) 120 | 121 | ## Computador de Programa Armazenado 122 | 123 | - Sequência de Instruções armazenadas dentro do computador 124 | - Construídos através de um conjunto pré-definido de instruções primitivas 125 | 1. Aritmética e Lógica 126 | 2. Testes simples 127 | 3. Movendo dados 128 | 129 | - Programa Especial (Interpretador) **executa cada instrução em ordem** 130 | - Usa testes para alterar o fluxo de control através de sequência 131 | - Para quando estiver pronto 132 | 133 | ## Primitivos Básicos 134 | 135 | - Turing mostrou que podemos **computar tudo** utilizando 6 primitivos 136 | - Linguagens de programação modernas possuem conjuntos de primitivos mais convenientes 137 | - Pode abstrair métodos para criar **novos primitivos** 138 | - Qualquer cálculo computável em uma linguagem é computável em qualquer outra linguagem de programação 139 | 140 | ## Criando Receitas 141 | 142 | - Uma linguagem de programação fornece um conjunto de **operações** primitivas 143 | - **Expressões** são complexas, mas combinações legais de primitivos em uma linguagem de programação 144 | - Expressões e Computações possuem **valores** e **sentido** em uma linguagem de programação 145 | 146 | ## Aspectos das Linguagens 147 | 148 | - Constructos Primitivos 149 | - Português: palavras 150 | - Linguagem de programação: números, strings, operadores simples 151 | - **Sintaxe** 152 | - Português: "gato cachorro garoto" -> invalida sintaticamente 153 | "gato abraça o garoto" -> valida sintaticamente 154 | - Linguagem de Programação: "oi"5 -> invalida sintaticamente 155 | 3.2*5 -> valida sintaticamente 156 | - **Semântica Estática** no qual strings sintaticamente válidas possuem sentido 157 | - Português: "Eu fome" -> valida sintaticamente, porém com erro de semântica 158 | - Linguagem de Programação: 3.2*5 -> valida sintaticamente 159 | 3+"oi" -> erro de semântica 160 | - **Semântica** é o sentido associado com uma string de símbolos sintaticamente correta com nenhum erro de semântica 161 | - Português: pode ter muitos sentidos "aviões voadores podem ser perigosos" 162 | - Linguagem de Programação: Possui apenas um sentido, porém talvez não seja a intenção do programador 163 | 164 | ## Quando Ocorrem Erros 165 | 166 | - Erros de Sintáxe 167 | - Comuns e fáceis de perceber 168 | 169 | - Erros de Semântica Estática 170 | - Algumas linguagens checam por eles antes de rodar o programa 171 | - Pode causar comportamento imprevisível 172 | 173 | - Nenhum erro de Semântica, porém um sentido diferente do que o programador desejava 174 | - Programa crasha, para de rodar 175 | - Programa roda para sempre 176 | - Programa dá uma resposta, porém diferente do esperado 177 | 178 | ## Programas em Python 179 | 180 | - Um programa é uma sequência de definições e comandos 181 | - Definições avaliadas 182 | - Comandos executados pelo Interpretador Python em uma shell 183 | - Comandos (afirmações) instruem o interpretador a fazerem algo 184 | - Podem ser digitados diretamente em uma shell ou guardados em um arquivo que é então lido na shell e avaliado 185 | 186 | ## Objetos 187 | 188 | - Programas manipulam **objetos de dados** 189 | - Objetos possuem um **tipo** que define os tipos de ações que os programas podem fazer com eles 190 | - Gabriel é um humano, sendo assim ele pode caminhar, falar, etc. 191 | - Pepe é um cachorro, sendo assim ela pode latir, rosnar, etc. 192 | - Objetos são 193 | - Escalares (não podem ser subdivididos) 194 | - Não-Escalares (possui uma estrutura interna que pode ser acessada) 195 | 196 | Agora que temos informações fundamentais básicas sobre a linguagem **Python**, vamos iniciar a configuração de nosso Ambiente de Programação. 197 | 198 | **Próximo Capítulo**: [Ambiente de Programação](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/02.Ambiente%20de%20Programa%C3%A7%C3%A3o.md) 199 | -------------------------------------------------------------------------------- /Capitulos/03.Sintaxe.md: -------------------------------------------------------------------------------- 1 | # Sintaxe 2 | 3 | ## Palavras-chave em **Python** 4 | 5 | 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. A seguir mostramos a lista de todas as palavras-chave: 6 | 7 | | **Nome** | **Descrição** | 8 | |----------|:-------------------------------------------------------------------------------------------------:| 9 | | and | operador lógico "e" | 10 | | as | capaz de criar um **[alias](https://pt.wikipedia.org/wiki/Alias_(comando))** | 11 | | assert | usado para **[debugging](https://www.inf.pucrs.br/flash/progbio/aulas/seq/build/progbio/WhatisDebugging.html)** | 12 | | async | usado para escrever aplicações **[asyncio](https://docs.python.org/3/library/asyncio-task.html)** | 13 | | await | usado para escrever aplicações **[asyncio](https://docs.python.org/3/library/asyncio-task.html)** | 14 | | break | para sair de um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 15 | | class | define uma **[classe](https://pt.wikipedia.org/wiki/Classe_(programação))** | 16 | | continue | continua para a nova iteração do **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 17 | | def | define uma **[função](http://www.inf.ufpr.br/cursos/ci067/Docs/NotasAula/notas-11_Fun_c_coes.html)** | 18 | | del | deleta um **[objeto](https://pt.wikipedia.org/wiki/Objeto_(ciência_da_computação))** | 19 | | elif | usado em **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)**, como else e if | 20 | | else | usado em **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)** | 21 | | except | usado com **[exceções](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)**, para tratar possíveis erros | 22 | | False | Valor **[booleano](https://pt.wikipedia.org/wiki/Booleano)**, resulta de operações de comparação | 23 | | 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 | 24 | | for | usado para criar um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** | 25 | | from | para importar partes específicas de um **[módulo](https://pt.wikipedia.org/wiki/Módulo_de_um_programa)** | 26 | | global | declara uma **[variável global](https://pt.wikipedia.org/wiki/Variável_global)** | 27 | | if | usado para **[comandos condicionais](https://pt.wikipedia.org/wiki/Estrutura_de_seleção)** | 28 | | import | usado para importar **[módulos](https://pt.wikipedia.org/wiki/Módulo_de_um_programa)** | 29 | | in | capaz de checar se um valor está presente em uma lista, tupla, etc | 30 | | is | testa se duas **[variáveis](https://pt.wikipedia.org/wiki/Variável_(programação))** são iguais | 31 | | lambda | cria uma **[função anônima](https://github.com/the-akira/Python-Iluminado/blob/master/17.Lambda.md)** | 32 | | None | representa um valor **[null](https://pt.wikipedia.org/wiki/Null_(programação))** | 33 | | nonlocal | declara uma **[variável](https://pt.wikipedia.org/wiki/Variável_(programação))** não-local | 34 | | not | **[operador lógico](https://pt.wikipedia.org/wiki/Operador_lógico)** de negação | 35 | | or | **[operador lógico](https://pt.wikipedia.org/wiki/Operador_lógico)** "ou" | 36 | | pass | comando null, um comando que não faz nada | 37 | | raise | dispara um **[exceção](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)** | 38 | | 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 | 39 | | True | Valor **[booleano](https://pt.wikipedia.org/wiki/Booleano)**, resulta de operações de comparação | 40 | | try | Comando de try, usado em conjunto com except | 41 | | while | Cria um **[loop](https://pt.wikipedia.org/wiki/Loop_(programação))** while | 42 | | with | usado para simplificar a lida com **[exceções](https://pt.wikipedia.org/wiki/Tratamento_de_exceção)** | 43 | | 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))** | 44 | 45 | Obtendo as palavras-chave através do **interpretador** Python 46 | 47 | ``` 48 | >>> import keyword 49 | >>> print(keyword.kwlist) 50 | ``` 51 | 52 | Veja que nos é retornado uma **lista** (Estrutura de Dados que veremos com mais detalhes em breve) com todas as palavras-chave da linguagem Python. 53 | 54 | ``` 55 | ['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'] 56 | ``` 57 | 58 | *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! 59 | 60 | --------------------------------------- 61 | 62 | ## Identificadores 63 | 64 | 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. 65 | 66 | --------------------------------------- 67 | 68 | ## Regras 69 | 70 | 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. 71 | Variáveis são **case sensitive** (idade, Idade e IDADE são três variáveis diferentes) 72 | Identificadores **não podem começar com dígitos:** 13variavel é inválido, porém variavel13 é aceito! 73 | Palavras-chave jamais podem ser usadas como identificadores! 74 | 75 | --------------------------------------- 76 | 77 | ## Indentação 78 | 79 | 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: 80 | 81 | ```python 82 | vida = 100 83 | 84 | if vida > 0: 85 | print("Você está vivo") 86 | ``` 87 | 88 | Caso você não utilize a indentação correta, Python irá disparar um erro. 89 | 90 | --------------------------------------- 91 | 92 | ## Comentários 93 | 94 | **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! 95 | Comentários começam com #, por exemplo: 96 | 97 | ```python 98 | #Este é um comentário 99 | print("Códigos comentados são muito mais fáceis de serem compreendidos") 100 | ``` 101 | 102 | **Python** também suporta docstrings, que são comentários que podem extender até mais linhas, veja: 103 | 104 | ```python 105 | """ 106 | Este é um comentário 107 | que abrange várias 108 | linhas do programa 109 | """ 110 | print("Procure sempre comentar o seu código") 111 | ``` 112 | 113 | 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/) 114 | 115 | **Próximo Capítulo**: [Tipos de Variáveis](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/04.Tipos%20de%20Vari%C3%A1veis.md) 116 | -------------------------------------------------------------------------------- /Capitulos/30.PythonMySQL.md: -------------------------------------------------------------------------------- 1 | # Python MySQL 2 | 3 | ## Iniciando 4 | 5 | Assim como muitas outras linguagens de programação, *Python também nos possibilita trabalharmos com banco de dados*. Existem diversos **sistemas gerenciadores de banco de dados** disponíveis, nesse guia específico trabalharemos com o **MySQL**, que é um dos mais populares e usados no mercado. Para seguir conosco, você precisa baixar o **MySQL**, que está disponível de forma gratuita em seu site oficial **https://www.mysql.com/downloads/**. 6 | 7 | ## MySQL Driver 8 | 9 | Para que possamos nos conectar com o **MySQL** através do **Python**, é necessário que instalemos o *driver de conexão*, para isso vamos utilizar o **PIP**, visto recentemente. Abra sua **interface de linha de comando** e digite: 10 | 11 | ``` 12 | pip install mysql-connector 13 | ``` 14 | 15 | Aguarde o download e o **driver** estará pronto para utilizarmos. Agora vamos confirmar se ele foi instalado corretamente: 16 | 17 | ```python 18 | import mysql.connector 19 | ``` 20 | 21 | Caso o comando tenha sido executado sem nenhum erro, estamos prontos para continuar! O primeiro passo agora é criar uma conexão com o banco de dados, para isso utilizaremos o nosso **nome de usuário** e **senha** do banco de dados **MySQL**. Lembre que você escolheu ambos durante o processo de instalação do banco de dados em sua máquina. 22 | 23 | ```python 24 | import mysql.connector 25 | 26 | meu_banco = mysql.connector.connect( 27 | host="localhost", 28 | user="python", 29 | passwd="python3" 30 | ) 31 | 32 | # Especificamos a conexão com o localhost (nossa própria máquina) e nosso usuário e senha. 33 | 34 | print(meu_banco) 35 | 36 | # 37 | ``` 38 | 39 | Veja que ele nos retorna um **objeto de conexão**, agora estamos prontos para *manipular o banco de dados* utilizando comandos **SQL**. 40 | 41 | ## Criando um Banco de Dados 42 | 43 | Agora vamos criar um banco de dados chamado banco, para isso vamos utilizar o comando SQL "CREATE DATABASE". 44 | 45 | ```python 46 | import mysql.connector 47 | 48 | meu_banco = mysql.connector.connect( 49 | host="localhost", 50 | user="python", 51 | passwd="python3" 52 | ) 53 | 54 | cursor = meu_banco.cursor() 55 | cursor.execute("CREATE DATABASE banco") 56 | ``` 57 | 58 | Caso nenhum erro tenha ocorrido, signifca que criamos nosso primeiro banco de dados com sucesso. Agora vamos checar se o banco de dados que criamos realmente está presente, para isso utilizaremos o comando **"SHOW DATABASES"**, este que vai mostrar todos os bancos presentes no nosso sistema. 59 | 60 | ```python 61 | import mysql.connector 62 | 63 | meu_banco = mysql.connector.connect( 64 | host="localhost", 65 | user="python", 66 | passwd="python3" 67 | ) 68 | 69 | cursor = meu_banco.cursor() 70 | 71 | cursor.execute("SHOW DATABASES") 72 | 73 | for x in cursor: 74 | print(x) 75 | 76 | # ('information_schema',) 77 | # ('banco',) 78 | # ('mysql',) 79 | # ('performance_schema',) 80 | # ('sys',) 81 | ``` 82 | 83 | ## Criando uma Tabela 84 | 85 | Para que possamos criar tabelas no nosso banco de dados, temos de utilizar o comando **"CREATE TABLE"**, lembre dessa vez de definir o nome do banco de dados que vamos usar durante a conexão. 86 | 87 | ```python 88 | import mysql.connector 89 | 90 | meu_banco = mysql.connector.connect( 91 | host="localhost", 92 | user="python", 93 | passwd="python3", 94 | database="banco" 95 | ) 96 | 97 | cursor = meu_banco.cursor() 98 | cursor.execute("CREATE TABLE usuario (nome VARCHAR(255), endereco VARCHAR(255))") # Caso execute sem erros, nossa tabela está criada 99 | 100 | # Agora vamos mostrar as tabelas do nosso banco de dados 101 | 102 | cursor.execute("SHOW TABLES") 103 | for x in cursor: 104 | print(x) 105 | 106 | # Veja que ele nos retorna nossa tabela ('usuario',) 107 | ``` 108 | 109 | ## Chave primária 110 | 111 | Ao criarmos uma tabela, é importante que tenhamos uma coluna que possua uma **chave única** para cada **registro**, esta chave se chama **chave primária**, para isso vamos utilizar o comando **"INT AUTO_INCREMENT PRIMARY KEY"** que irá inserir um número único para cada registro, começando por 1 e incrementando para cada registro que vier. 112 | 113 | ```python 114 | cursor.execute("CREATE TABLE usuario (id INT AUTO_INCREMENT PRIMARY KEY, nome VARCHAR(255), endereco VARCHAR(255))") 115 | ``` 116 | 117 | Veja que ocorre um problema, pois já possuímos a tabela no nosso banco, para contornarmos essa situação, vamos utilizar o comando **ALTER TABLE**, que irá alterar a tabela com essa nova coluna. 118 | 119 | ```python 120 | cursor.execute("ALTER TABLE usuario ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY") 121 | ``` 122 | 123 | ## Inserindo valores na Tabela 124 | 125 | De nada adianta termos uma tabela se não for para preenchermos com valores para uso futuro, não é mesmo? Para essa tarefa vamos utilizar o comando **"INSERT INTO"**. 126 | 127 | ```python 128 | import mysql.connector 129 | 130 | meu_banco = mysql.connector.connect( 131 | host="localhost", 132 | user="python", 133 | passwd="python3", 134 | database="banco" 135 | ) 136 | 137 | cursor = meu_banco.cursor() 138 | 139 | comando_sql = "INSERT INTO usuario (nome, endereco) VALUES (%s, %s)" 140 | valores = ("João", "Avenida 66") 141 | cursor.execute(comando_sql, valores) 142 | 143 | meu_banco.commit() 144 | 145 | print(cursor.rowcount, "registro inserido") # 1 registro inserido 146 | ``` 147 | 148 | Veja que foi necessário utilizarmos o comando **meu_banco.commit()**, que é necessário para confirmarmos as mudanças no nosso banco. 149 | 150 | ## Inserir múltiplas linhas 151 | 152 | Para que possamos inserir **múltiplas linhas** de uma só vez, podemos executar o método **executemany()**, o segundo parâmetro desse método é uma **lista de tuplas** que contém os dados que vamos inserir. 153 | 154 | ```python 155 | import mysql.connector 156 | 157 | meu_banco = mysql.connector.connect( 158 | host="localhost", 159 | user="python", 160 | passwd="python3", 161 | database="banco" 162 | ) 163 | 164 | cursor = meu_banco.cursor() 165 | comando_sql = "INSERT INTO usuario (nome, endereco) VALUES (%s, %s)" 166 | valores = [ 167 | ("José", "Rua Maria"), 168 | ("Paulo", "Avenida Carlos"), 169 | ("Pedro", "Rua 190") 170 | ] 171 | 172 | cursor.executemany(comando_sql, valores) 173 | 174 | meu_banco.commit() 175 | 176 | print(cursor.rowcount, "foram inseridos") # 3 foram inseridos 177 | ``` 178 | 179 | ## Selecionando valores da Tabela 180 | 181 | Para que possamos selecionar os valores que inserimos, utilizamos o comando **"SELECT"**. 182 | 183 | ```python 184 | import mysql.connector 185 | 186 | meu_banco = mysql.connector.connect( 187 | host="localhost", 188 | user="python", 189 | passwd="python3", 190 | database="banco" 191 | ) 192 | 193 | cursor = meu_banco.cursor() 194 | 195 | cursor.execute("SELECT * FROM usuario") # O * específica que queremos todos os registros da tabela 196 | 197 | resultado = cursor.fetchall() # Veja que usamos o método fetchall() que trará todas as linhas do nosso último comando executado 198 | 199 | for x in resultado: 200 | print(x) 201 | 202 | # (1, 'João', 'Avenida 66') 203 | # (2, 'José', 'Rua Maria') 204 | # (3, 'Paulo', 'Avenida Carlos') 205 | # (4, 'Pedro', 'Rua 190') 206 | ``` 207 | 208 | Também podemos selecionar apenas determinadas **colunas**, por exemplo 209 | 210 | ```python 211 | cursor.execute("SELECT nome, endereco FROM usuario") 212 | ``` 213 | 214 | ## Deletando registros 215 | 216 | Podemos também **deletar** registros da nossa tabela, para isso vamos usar o comando **"DELETE FROM"**. 217 | 218 | ```python 219 | import mysql.connector 220 | 221 | meu_banco = mysql.connector.connect( 222 | host="localhost", 223 | user="python", 224 | passwd="python3", 225 | database="banco" 226 | ) 227 | 228 | cursor = meu_banco.cursor() 229 | 230 | comando_sql = "DELETE FROM usuario WHERE endereco = 'Avenida 66'" 231 | cursor.execute(sql) 232 | meu_banco.commit() 233 | 234 | print(cursor.rowcount, "registro excluído") # 1 registro excluído 235 | ``` 236 | 237 | **Importante:** Perceba que utilizamos a claúsula **WHERE** no nosso comando, fazendo com que possamos especificar o registro a ser excluído, porém, se você deixar de usar ela, todos os registros serão deletados, *então tenha muita atenção!* 238 | 239 | ## Deletando uma Tabela 240 | 241 | Podemos facilmente deletar uma tabela com o comando **"DROP TABLE"** 242 | 243 | ```python 244 | import mysql.connector 245 | 246 | meu_banco = mysql.connector.connect( 247 | host="localhost", 248 | user="python", 249 | passwd="python3", 250 | database="banco" 251 | ) 252 | 253 | cursor = meu_banco.cursor() 254 | 255 | comando_sql = "DROP TABLE usuario" 256 | 257 | cursor.execute(comando_sql) 258 | ``` 259 | 260 | ## Atualizando a nossa Tabela 261 | 262 | Caso queiramos atualizar nossa tabela, podemos utilizar o comando **"UPDATE"**, nesse caso vamos alterar o endereço 'Rua Maria' para 'Rua José' 263 | 264 | ```python 265 | import mysql.connector 266 | 267 | meu_banco = mysql.connector.connect( 268 | host="localhost", 269 | user="python", 270 | passwd="python3", 271 | database="banco" 272 | ) 273 | 274 | cursor = meu_banco.cursor() 275 | 276 | comando_sql = "UPDATE usuario SET endereco = 'Rua José' WHERE address = 'Rua Maria'" 277 | 278 | cursor.execute(comando_sql) 279 | 280 | meu_banco.commit() 281 | 282 | print(cursor.rowcount, "registro afetado") # 1 registro afetado 283 | ``` 284 | 285 | Esta foi uma pequena introdução ao *Python em conjunto com MySQL*, veja que as possibilidades são grandes e existe muito mais pela frente, apenas demonstramos alguns comandos **SQL**, porém existem diversos, há toda uma literatura voltada para bancos de dados relacionais, nesse caso trabalhamos com apenas uma tabela, mas podemos ter diversas e relacionar umas com as outras. Banco de dados é uma área vasta e que exige muito estudo, eles estão presentes em grandes corporações e guardam quantidades inimagináveis de informação, com certeza um grande tópico para ser estudado! 286 | 287 | **Próximo Capítulo**: [MongoDB](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/31.PythonMongoDB.md) 288 | -------------------------------------------------------------------------------- /Capitulos/08.Listas.md: -------------------------------------------------------------------------------- 1 | # Listas 2 | 3 | ![img](https://i.imgur.com/0ErRqBx.jpg) 4 | 5 | Existem quatro tipos de dados de coleção na linguagem de programação Python, são eles: 6 | 7 | - **[Listas](https://docs.python.org/3/library/stdtypes.html#lists)**: Coleção **ordenada** e **mutável**. Permite membros duplicados. 8 | - **[Tuplas](https://docs.python.org/3/library/stdtypes.html#tuples)**: Coleção **ordenada** e **imutável**. Permite membros duplicados. 9 | - **[Sets](https://docs.python.org/3/tutorial/datastructures.html#sets)**: Coleção **não-ordenada** e **não-indexada**. Não permite membros duplicados. 10 | - **[Dicionários](https://docs.python.org/3/tutorial/datastructures.html#dictionaries)**: Coleção **não-ordenada**, **mutável** e indexável. Não permite membros duplicados. 11 | 12 | Dos **dados compostos**, usados para agrupar outros valores. A mais versátil é a **lista**, que pode ser escrita como uma *lista de valores separados por vírgula (itens) entre colchetes*. As listas podem conter itens de tipos diferentes, mas geralmente os itens têm o mesmo tipo. 13 | 14 | ```python 15 | lista1 = ['física', 'química', 'matemática'] 16 | lista2 = [1, 2, 3, 4, 5] 17 | lista3 = [1, 2.3, "Rafael"] 18 | ``` 19 | 20 | Semelhantes às **strings**, as **listas** também consideram o índice começando por **0**, além disso, as listas podem ser manipuladas de várias formas, como **concatenadas** e **cortadas**. 21 | 22 | --------------------------------------- 23 | 24 | ## Acessando itens: 25 | 26 | ```python 27 | print(lista1[0:2]) # ['física', 'química'] 28 | print(lista2[2]) # 3 29 | print(lista3[-1]) # Rafael 30 | ``` 31 | 32 | --------------------------------------- 33 | 34 | ## Modificando itens: 35 | 36 | ```python 37 | lista1[0] = "computação" 38 | print(lista1[0]) # computação 39 | ``` 40 | 41 | --------------------------------------- 42 | 43 | ## Percorrendo os itens da lista: 44 | 45 | ```python 46 | for x in lista1: # Percorre cada elemento da lista 47 | print(x) # Imprime os elementos 48 | ``` 49 | 50 | Fique tranquilo que veremos o **for loop** com mais detalhes em breve 51 | 52 | --------------------------------------- 53 | 54 | ## Checando se um valor existe em uma lista: 55 | 56 | ```python 57 | print("química" in lista1) # True 58 | ``` 59 | 60 | --------------------------------------- 61 | 62 | ## Também podemos verificar o tamanho de uma lista: 63 | 64 | ```python 65 | print(len(lista1)) # 2 66 | ``` 67 | 68 | --------------------------------------- 69 | 70 | ## Adicionando itens a uma lista: 71 | 72 | ```python 73 | lista1.append("português") 74 | print(lista1) # ['química', 'matemática', 'português'] 75 | ``` 76 | 77 | --------------------------------------- 78 | 79 | ## Podemos também usar o método **insert()** para inserirmos itens em uma posição específica: 80 | 81 | ```python 82 | lista1.insert(1, "história") 83 | print(lista1) # ['química', 'história', 'matemática', 'português'] 84 | ``` 85 | 86 | --------------------------------------- 87 | 88 | ## Removendo itens de uma lista 89 | 90 | - É possível deletar um elemento em um **índice específico** com `del(L[indice])` 91 | - É possível remover elementos no **fim da lista** com `L.pop()`, retornará o elemento removido 92 | - É possível remover um **elemento específico** com `L.remove(elemento)` 93 | - Busca pelo elemento e remove ele 94 | - Se o elemento ocorre múltiplas vezes na lista, remove a primeira ocorrência 95 | - Se o elemento não estiver presente na lista, ocorrerá um erro 96 | 97 | ``` 98 | L = [2, 1, 3, 6, 3, 7, 0] 99 | L.remove(2) # Causa mutação em L = [1, 3, 6, 3, 7, 0] 100 | L.remove(3) # Causa mutação em L = [1, 6, 3, 7, 0] 101 | del(L[1]) # Causa mutação em L = [1, 3, 7, 0] 102 | L.pop() # retorna 0 e causa mutação em L = [1, 3, 7] 103 | ``` 104 | 105 | ```python 106 | lista1.remove("química") 107 | print(lista1) # ['história', 'matemática', 'português'] 108 | ``` 109 | 110 | ```python 111 | del lista1[0] 112 | print(lista1) # ['matemática', 'português'] 113 | ``` 114 | 115 | Fique atento, caso não seja especificado um índice, **del** vai eliminar sua lista por completo! 116 | 117 | --------------------------------------- 118 | 119 | ## O método **pop()** 120 | 121 | ```python 122 | lista1.pop() 123 | print(lista1) # ['matemática'] 124 | ``` 125 | 126 | --------------------------------------- 127 | 128 | ## O método **clear()** esvazia a lista 129 | 130 | ```python 131 | lista1.clear() 132 | print(lista1) # [] 133 | ``` 134 | 135 | --------------------------------------- 136 | 137 | ## Também é possível construirmos listas através do método construtor **list()**, veja: 138 | 139 | ```python 140 | lista = list((1,2,3)) 141 | print(lista) # [1,2,3] 142 | ``` 143 | 144 | --------------------------------------- 145 | 146 | ## Podemos executar operações com listas: 147 | 148 | ```python 149 | l1 = [1,2] 150 | l2 = [3,4] 151 | l3 = [2,4,6,1,5] 152 | ``` 153 | 154 | --------------------------------------- 155 | 156 | ## Concatenação: 157 | 158 | ```python 159 | print(l1+l2) # [1,2,3,4] 160 | ``` 161 | 162 | --------------------------------------- 163 | 164 | ## Repetição: 165 | 166 | ```python 167 | print(l1*3) # [1, 2, 1, 2, 1, 2] 168 | ``` 169 | 170 | --------------------------------------- 171 | 172 | ## Organizando com o método **sort()**: 173 | 174 | ```python 175 | l3.sort() 176 | print(l3) # [1,2,4,5,6] 177 | ``` 178 | 179 | ```python 180 | lista = [9, 1, 8, 2, 7, 3, 6, 4, 5] 181 | 182 | s_lista = sorted(lista) # ordena em ordem ascendente 183 | print(s_lista) 184 | 185 | r_lista = sorted(lista, reverse=True) # ordena em ordem decrescente 186 | print(r_lista) 187 | 188 | lista.sort() 189 | print(lista) 190 | ``` 191 | 192 | ## Iterando sob uma Lista 193 | 194 | - Computar a **soma de elementos** de uma lista 195 | - Padrão comum, iterar sob os elementos da lista 196 | 197 | ```python 198 | L = [1,3,4,10,33,13,12] 199 | total = 0 200 | for i in range(len(L)): 201 | total += L[i] 202 | print(total) 203 | ``` 204 | 205 | ```python 206 | total = 0 207 | for i in L: 208 | total += i 209 | print(total) 210 | ``` 211 | 212 | --------------------------------------- 213 | 214 | ## Compreensões de Listas 215 | 216 | As compreensões de **listas** são utilizadas para criarmos novas **listas** através de outros **[iteráveis](https://stackoverflow.com/questions/9884132/what-exactly-are-iterator-iterable-and-iteration)**. Vejamos alguns exemplos: 217 | 218 | ```python 219 | # Define a lista numeros 220 | numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 221 | 222 | # Método comum com lista 223 | lista = [] 224 | for n in numeros: 225 | lista.append(n) 226 | print(lista) 227 | 228 | # Compreensão de lista 229 | minha_lista = [n for n in numeros] 230 | print(minha_lista) 231 | 232 | # Método comum com lista 233 | lista_2 = [] 234 | for n in numeros: 235 | lista_2.append(n*n) 236 | print(lista_2) 237 | 238 | # Compreensão de lista 239 | minha_lista_2 = [n*n for n in numeros] 240 | print(minha_lista_2) 241 | 242 | # Método comum com lista 243 | minha_lista_3 = [] 244 | for n in numeros: 245 | if n%2 == 0: 246 | minha_lista_3.append(n) 247 | print(minha_lista_3) 248 | 249 | # Compreensão de lista 250 | minha_lista_4 = [n for n in numeros if n%2 == 0] 251 | print(minha_lista_4) 252 | 253 | # Método comum com lista 254 | minha_lista_5 = [] 255 | for letra in 'abcd': 256 | for num in range(4): 257 | minha_lista_5.append((letra,num)) 258 | print(minha_lista_5) 259 | 260 | # Compreensão de lista 261 | minha_lista_6 = [(letra,num) for letra in 'abcd' for num in range(4)] 262 | print(minha_lista_6) 263 | ``` 264 | 265 | --------------------------------------- 266 | 267 | ## Métodos das Listas 268 | 269 | Existem diversos métodos construídos que podem ser usados com as listas para nos auxiliar em soluções. 270 | 271 | | **Método** | **Descrição** | 272 | |-------------|----------------------------------------------------------------| 273 | | append() | Adiciona um único elemento para a lista. | 274 | | extend() | Adiciona um elemento de uma lista para outra lista | 275 | | insert() | Insere um elemento na lista | 276 | | remove() | Remove um elemento da lista | 277 | | index() | Retorna o índice de um elemento na lista | 278 | | count() | Retorna ocorrências de um elemento na lista | 279 | | pop() | Remove elemento de um determinado índice | 280 | | reverse() | Inverte a lista | 281 | | sort() | Organiza os elementos da lista | 282 | | copy() | Retorna uma cópia da lista | 283 | | clear() | Remove todos os itens da lista | 284 | | any() | Checa se algum elemento do iterável é True | 285 | | all() | Retorna True quando todos os elementos em um iterável são True | 286 | | ascii() | Retorna uma String | 287 | | bool() | Converte um valor para Boolean | 288 | | enumerate() | Retorna um Objeto Enumerate | 289 | | filter() | Constrói um iterador dos elementos que são True | 290 | | iter() | Retorna um iterador para um Objeto | 291 | | list() | Função que cria uma lista em Python | 292 | | len() | Retorna o comprimento / extensão da lista | 293 | | max() | Retorna o maior elemento | 294 | | min() | Retorna o menor elemento | 295 | | map() | Aplica uma função e retorna uma lista | 296 | | reversed() | Retorna um iterador invertido da sequência | 297 | | slice() | Cria um Objeto slice especificado por range() | 298 | | sorted() | Retorna uma lista organizada de um determinado iterável | 299 | | sum() | Adiciona os itens de um iterável | 300 | | zip() | Retorna um iterador de tuplas | 301 | 302 | Como podemos ver, as listas são uma estrutura de dados fundamental na linguagem Python e pode colaborar muito com nossos projetos devido a sua versatilidade. 303 | 304 | **Próximo Capítulo**: [Tuplas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/09.Tuplas.md) 305 | -------------------------------------------------------------------------------- /Capitulos/31.PythonMongoDB.md: -------------------------------------------------------------------------------- 1 | # Python MongoDB 2 | 3 | Como vimos no capítulo anterior, **Python** pode ser usado em conjunto com **banco de dados**, anteriormente utilizamos os bancos de dados relacionais **SQL**, agora vamos dar um passo a frente e trabalhar com **NOSQL**. 4 | 5 | ## MongoDB 6 | 7 | **MongoGB** é um dos mais populares banco de dados **NOSQL**, ele permite guardarmos nossos dados no modelo **JSON**, o que torna o nosso banco de dados flexível e escalável. Para que você possa continuar conosco nesse capítulo é necessário que você faça o download do MongoDB que está disponibilizado gratuitamente em **https://www.mongodb.com**. 8 | 9 | ## PyMongo 10 | 11 | Para que possamos trabalhar com o *MongoDB em Python* precisamos instalar o driver **PyMongo**, para isso utilizaremos o **PIP**. 12 | 13 | ``` 14 | pip install pymongo 15 | ``` 16 | 17 | Aguarde o download e instalação. Para confirmarmos se está tudo certo, vamos digitar no nosso **interpretador** 18 | 19 | ```python 20 | import pymongo 21 | ``` 22 | 23 | Caso nenhum erro tenha sido disparado, signifca que estamos com o **pymongo** instalado e pronto para ser usado. 24 | 25 | ## Criando um Banco de Dados 26 | 27 | Para criarmos um banco de dados no MongoDB é necessário criarmos um *objeto MongoClient*, em seguida devemos especificar uma **URL** de conexão com o *endereço IP correto* e o *nome do banco de dados*, caso o banco de dados não exista, MongoDB criará para nós e fará uma conexão. 28 | 29 | ```python 30 | import pymongo 31 | 32 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 33 | 34 | meu_banco = cliente['banco_de_dados'] 35 | 36 | print(meu_banco) # Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'base_de_dados') 37 | ``` 38 | 39 | Importante lembrarmos que no MongoDB um banco de dados *não é criado até que ele receba conteúdo*. MongoDB esperará até que criemos a **coleção** (similar a tabela SQL), com pelo menos um **documento** (similar ao registro SQL) antes de criar o banco de dados. 40 | 41 | ## Verificando se um Banco de Dados existe 42 | 43 | Podemos checar se um determinado banco de dados existe executando o método **list_database_names()** 44 | 45 | ```python 46 | print(cliente.list_database_names()) # ['local', 'admin'] 47 | ``` 48 | 49 | Observe que nosso banco anterior ainda não está presente, precisamos **populá-lo!!!** 50 | 51 | ## Criando uma Coleção 52 | 53 | No MongoDB chamamos de coleção o que no SQL seriam as tabelas, são os compartimentos que guardamos nossos dados. Para criarmos uma coleção no MongoDB vamos usar o *objeto do banco de dados* e especificar o nome da coleção que queremos criar. 54 | 55 | ```python 56 | import pymongo 57 | 58 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 59 | 60 | meu_banco = cliente['banco_de_dados'] 61 | colecao = meu_banco['usuarios'] 62 | ``` 63 | 64 | Lembrando novamente que a coleção não será criada até que receba conteúdo!!! 65 | 66 | ## Checando se uma coleção existe 67 | 68 | ```python 69 | print(meu_banco.list_collection_names()) # [] 70 | ``` 71 | 72 | Veja que nos retornou uma lista vazia, isso porque nossa coleção só será criada de fato quando *inserirmos dados nela*, aguarde que logo teremos nossa tão espera coleção! 73 | 74 | ## Inserindo Documentos no MongoDB 75 | 76 | Um documento no MongoDB é como um registro nos bancos de dados SQL. Para que possamos inserir um documento numa coleção do MongoDB usaremos o método **insert_one()**. O primeiro parâmetro do método **insert_one()** é um dicionário contendo nomes e valores de cada campo do documento que queremos inserir. 77 | 78 | ```python 79 | import pymongo 80 | 81 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 82 | 83 | meu_banco = cliente['banco_de_dados'] 84 | colecao = meu_banco['usuarios'] 85 | 86 | dicionario = { "nome": "José", "endereco": "Rua 33" } 87 | 88 | x = colecao.insert_one(dicionario) 89 | 90 | print(x) # 91 | ``` 92 | 93 | Veja que nos foi retornado um objeto **InsertOneResult**, que tem a propriedade **inserted_id** que guarda o **id** do documento inserido. Agora vamos inserir outro documento na coleção **usuarios** e retornaremos o valor do campo **_id**. 94 | 95 | ```python 96 | dic = { "nome": "Pedro", "endereco": "Rua 47" } 97 | 98 | y = colecao.insert_one(dic) 99 | 100 | print(y.inserted_id) # 5bda98bc02aa174002cba41f 101 | ``` 102 | 103 | Observe que em nenhum momento especificamos um **_id**, *MongoDB o fez automaticamente* para nós e ele o fará sempre que não especificarmos. 104 | 105 | ## Inserindo múltiplos documentos 106 | 107 | **PyMongo** nos permite inserir diversos documentos em uma coleção, para isso utilizamos o método **insert_many()**. O primeiro parâmetro de **insert_many()** é uma lista contendo dicionários dos dados que queremos inserir. 108 | 109 | ```python 110 | import pymongo 111 | 112 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 113 | 114 | meu_banco = cliente['banco_de_dados'] 115 | colecao = meu_banco['usuarios'] 116 | 117 | lista = [ 118 | { "_id": 1, "nome": "Eduardo", "endereco": "Rua 37"}, 119 | { "_id": 2, "nome": "Maria", "endereco": "Avenida 27"}, 120 | { "_id": 3, "nome": "Julio", "endereco": "Rua 67"}, 121 | { "_id": 4, "nome": "Marcos", "endereco": "Rua 21"}, 122 | { "_id": 5, "nome": "Marisa", "endereco": "Avenida 345"} 123 | ] 124 | 125 | z = colecao.insert_many(lista) 126 | 127 | print(z.inserted_ids) # [1, 2, 3, 4, 5] 128 | ``` 129 | 130 | Observe que dessa vez inserimos manualmente os **_ids**, porém você pode omití-los se quiser! 131 | 132 | ## Buscando dados no MongoDB 133 | 134 | Para selecionarmos dados de uma coleção no MongoDB podemos usar o método **find_one()** que nos trará a primeira ocorrência na seleção. 135 | 136 | ```python 137 | import pymongo 138 | 139 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 140 | 141 | meu_banco = cliente['banco_de_dados'] 142 | colecao = meu_banco['usuarios'] 143 | 144 | busca = colecao.find_one() 145 | 146 | print(busca) # {'nome': 'José', 'endereco': 'Rua 33', '_id': ObjectId('5bda981602aa174002cba41e')} 147 | ``` 148 | 149 | ## Buscando todos os dados 150 | 151 | O método **find()** nos permite buscarmos por todas as ocorrências, o primeiro parâmetro do método **find()** é um *objeto de query*, nesse caso específico vamos deixá-lo vazio para retornarmos todos os documentos da coleção. 152 | 153 | ```python 154 | import pymongo 155 | 156 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 157 | 158 | meu_banco = cliente['banco_de_dados'] 159 | colecao = meu_banco['usuarios'] 160 | 161 | for x in colecao.find(): 162 | print(x) 163 | 164 | # {'nome': 'José', 'endereco': 'Rua 33', '_id': ObjectId('5bda981602aa174002cba41e')} 165 | # {'nome': 'Pedro', 'endereco': 'Rua 47', '_id': ObjectId('5bda98bc02aa174002cba41f')} 166 | # {'nome': 'Eduardo', 'endereco': 'Rua 37', '_id': 1} 167 | # {'nome': 'Maria', 'endereco': 'Avenida 27', '_id': 2} 168 | # {'nome': 'Julio', 'endereco': 'Rua 67', '_id': 3} 169 | # {'nome': 'Marcos', 'endereco': 'Rua 21', '_id': 4} 170 | # {'nome': 'Marisa', 'endereco': 'Avenida 345', '_id': 5} 171 | ``` 172 | 173 | ## Deletando documentos 174 | 175 | Para deletarmos documentos utilizamos o método **delete_one()**, o primeiro parâmetro do método **delete_one()** é um *objeto query* definindo o documento a ser deletado. Importante, se o query encontrar mais de um documento, somente a primeira ocorrência será deletada. 176 | 177 | ```python 178 | import pymongo 179 | 180 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 181 | 182 | meu_banco = cliente['banco_de_dados'] 183 | colecao = meu_banco['usuarios'] 184 | 185 | query = { "endereco": "Rua 21" } 186 | 187 | colecao.delete_one(query) 188 | ``` 189 | 190 | ## Deletando vários documentos 191 | 192 | Caso queiramos deletar mais de um documento, temos o método **delete_many()** para nos auxiliar, que recebe como primeiro parâmetro um objeto query que definirá quais documentos deletar. 193 | 194 | ```python 195 | import pymongo 196 | 197 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 198 | 199 | meu_banco = cliente['banco_de_dados'] 200 | colecao = meu_banco['usuarios'] 201 | 202 | minha_query = { "endereco" : {"$regex": "^A"} } 203 | 204 | x = colecao.delete_many(minha_query) 205 | ``` 206 | 207 | Veja que utilizamos uma expressão regular, nesse caso todos os endereços que começarem com **A** vão ser deletados. Caso seja necessário deletar todos os documentos, utilizamos o método **delete_many()** passando um *objeto vazio*, veja 208 | 209 | ```python 210 | x = colecao.delete_many({}) 211 | ``` 212 | 213 | ## Deletando uma coleção 214 | 215 | Podemos deletar uma coleção de forma muito simples com o método **drop()**, nesse caso vamos deletar nossa coleção de usuários 216 | 217 | ```python 218 | import pymongo 219 | 220 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 221 | 222 | meu_banco = cliente['banco_de_dados'] 223 | colecao = meu_banco['usuarios'] 224 | 225 | colecao.drop() 226 | ``` 227 | 228 | O método **drop()** irá retornar **True** se a coleção for deletada com sucesso, caso contrário retornará **False** (se ela não existir). 229 | 230 | ## Atualizando Coleções 231 | 232 | Podemos atualizar nossos documentos com o método **update_one()**, que recebe como primeiro parâmetro um *objeto query* definindo o documento a ser atualizado, se o query encontrar mais de um elemento, somente a primeira ocorrência será atualizada, o segundo parâmetro é um objeto definindo os novos valores do documento. 233 | 234 | ```python 235 | import pymongo 236 | 237 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 238 | 239 | meu_banco = cliente['banco_de_dados'] 240 | colecao = meu_banco['usuarios'] 241 | 242 | query = { "endereco": "Rua 37" } 243 | novos_valores = { "$set": { "endereco": "Rua 200"} } 244 | 245 | colecao.update_one(query, novos_valores) 246 | 247 | for x in colecao.find(): 248 | print(x) 249 | 250 | # {'nome': 'José', 'endereco': 'Rua 33', '_id': ObjectId('5bda981602aa174002cba41e')} 251 | # {'nome': 'Pedro', 'endereco': 'Rua 47', '_id': ObjectId('5bda98bc02aa174002cba41f')} 252 | # {'nome': 'Eduardo', 'endereco': 'Rua 200', '_id': 1} 253 | # {'nome': 'Julio', 'endereco': 'Rua 67', '_id': 3} 254 | ``` 255 | 256 | ## Atualizando diversas Coleções 257 | 258 | Para atualizarmos todos os documentos que atendam ao critério de nosso query, utilizamos o método **update_many()**. Nesse caso vamos atualizar todos os endereços que começam com a letra **R**. 259 | 260 | ```python 261 | import pymongo 262 | 263 | cliente = pymongo.MongoClient("mongodb://localhost:27017/") 264 | 265 | meu_banco = cliente['banco_de_dados'] 266 | colecao = meu_banco['usuarios'] 267 | 268 | minha_query = { "endereco": { "$regex": "^R"} } 269 | valores_novos = { "$set": { "nome": "Avenida" } } 270 | 271 | x = colecao.update_many(minha_query, valores_novos) 272 | 273 | print(x.modified_count, "documentos atualizados") # 4 documentos atualizados 274 | ``` 275 | 276 | Esse pequeno capítulo teve como objetivo nos mostrar como podemos trabalhar com **MongoDB** no **Python**, embora seja uma tecnologia "recente", os bancos de dados NOSQL estão crescendo muito e nos prometem muita *flexibilidade e escalabilidade*. 277 | 278 | **Próximo Capítulo**: [Grandes Bibliotecas](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/32.Grandes%20Bibliotecas%20e%20Ferramentas.md) 279 | -------------------------------------------------------------------------------- /Capitulos/16.Funções.md: -------------------------------------------------------------------------------- 1 | # Funções 2 | 3 | Uma **função** é um bloco de código **organizado** e **reutilizável** que é capaz de realizar uma **determinada ação**. Funções nos ajudam a deixar o nosso código mais **modular**, trazendo a possibilidade de **reusabilidade**. Como vimos ao longo do guia, Python já nos traz várias funções pré-construídas, como por exemplo **print()** e **range()**, mas também é possível criarmos nossas próprias funções! 4 | 5 | --------------------------------------- 6 | 7 | ## Anatomia das Funções 8 | 9 | Podemos imaginar as **funções** como um **mecanismo** capaz de receber valores como **input** e então realizar operações nesses valores e retornar um **output** 10 | 11 | ![img](https://i.imgur.com/UlwSSWI.png) 12 | 13 | --------------------------------------- 14 | 15 | ## Características das Funções 16 | 17 | - Possuem um **nome** 18 | - Possuem **parâmetros** (0 ou mais) 19 | - Possuem **docstrings** (opcional, porém recomendado) 20 | - Possuem um **corpo** 21 | - **Retornam** algo 22 | 23 | --------------------------------------- 24 | 25 | ## Definindo uma Função 26 | 27 | Para definir uma **função** é necessário que sigamos algumas regras 28 | 29 | - Bloco de funções começam com a palavra-chave **def** seguido do nome da função e parenteses **()**. 30 | - Parâmetros de input ou argumentos (dados fornecidos por nós) devem ser colocados entre parenteses **()** 31 | - A palavra-chave **return [expressão]** sai da função, opcionalmente passando um parâmetro para o chamador. O comando de retorno sem argumentos é o mesmo que return None 32 | - Opcionalmente podemos usar strings de documentação (docstrings) para descrever o que nossa função faz 33 | 34 | Por exemplo: 35 | 36 | ```python 37 | def oi(nome): 38 | """ 39 | Essa função cumprimentará a pessoa passada por parâmetro 40 | """ 41 | print("Olá {0} Seja bem-vindo".format(nome)) 42 | ``` 43 | 44 | A **função** foi criada e está definida, porém nada aconteceu. Para que ela possa funcionar precisamos **invocá-la**, para isso chamaremos ela por seu nome e passaremos os **parâmetros** requisitados por ela 45 | 46 | ```python 47 | oi("Gabriel") # Olá Gabriel Seja bem-vindo 48 | ``` 49 | 50 | --------------------------------------- 51 | 52 | ## Parâmetros padrão 53 | 54 | Podemos definir **parâmetros padrão** para caso a função seja invocada sem nenhum parâmetro, estes preencherão as opções 55 | 56 | ```python 57 | def minha_func(valor=100): 58 | print("O valor definido foi: " + str(valor)) 59 | 60 | minha_func() 61 | minha_func(10) 62 | minha_func(33) 63 | ``` 64 | 65 | --------------------------------------- 66 | 67 | ## Docstring 68 | 69 | A primeira string depois do cabeçalho da função é chamada de docstring, é uma **string** usada para especificar a funcionalidade da nossa função, e embora seja opcional, vos lembro que documentar é uma importante prática de programação, uma vez que possivelmente outras pessoas estarão lendo nosso código, inclusive é importante até mesmo para você lembrar o que você fez! Caso queiramos ver o docstring de uma função 70 | 71 | ```python 72 | print(oi.__doc__) 73 | ``` 74 | 75 | --------------------------------------- 76 | 77 | ## O comando return 78 | 79 | O comando **return** nos permite fazer com que a função retorne um valor e possamos armazená-lo em uma variável, por exemplo: 80 | 81 | ```python 82 | def func(x): 83 | return x + 1 84 | 85 | y = func(1) 86 | z = func(2) 87 | print(y) # 2 88 | print(z) # 3 89 | ``` 90 | 91 | --------------------------------------- 92 | 93 | ## Escopo da Variável 94 | 95 | - **Parâmetro formal** se conecta com o valor do **parâmetro real** quando a função é chamada 96 | - Um novo **escopo/quadro/ambiente** é criado quando entra uma função 97 | - **Escopo** é o mapeamento de nomes para objetos 98 | 99 | ```python 100 | # Definição da Função 101 | def f(x): # parâmetro formal 102 | x += 1 103 | print('Em f(x): x = ',x) 104 | return x 105 | 106 | # Código principal do Programa 107 | # -> Inicializa a variável x 108 | # -> faz uma chamada de função f(x) 109 | # -> atribui o retorno da função para a variável z 110 | x = 10 111 | z = f(x) # parâmetro real 112 | print(z) 113 | ``` 114 | 115 | --------------------------------------- 116 | 117 | ## Funções como Argumentos 118 | 119 | - Argumentos podem assumir qualquer tipo, até mesmo funções 120 | 121 | ```python 122 | def func_a(): 123 | print('dentro da func_a') 124 | def func_b(y): 125 | print('dentro da func_b') 126 | return y 127 | def func_c(z): 128 | print('dentro da func_c') 129 | return z() 130 | print(func_a()) # chama a função func_a, não recebe parâmetros 131 | print(5+func_b(2)) # chama a função func_b, recebe um parâmetro 132 | print(func_c(func_a)) # chama a função func_c, recebe outra função como parâmetro 133 | ``` 134 | 135 | - A função `func_a` retorna `None` 136 | - A função `func_b` retorna `2` 137 | - A função `func_c` recebe a `func_a` como parâmetro, que por sua vez retorna `None` 138 | 139 | --------------------------------------- 140 | 141 | ## Exemplo do Escopo 142 | 143 | - Dentro de uma função, **podemos acessar** uma variável definida fora dela 144 | - Dentro de uma função, **não podemos modificar** uma variável definida fora dela, na verdade podemos utilizando a variável **global**, mas não é o ideal 145 | 146 | ```python 147 | def f(y): 148 | # x é redefinido no escopo de f 149 | x = 1 150 | x += 1 151 | print(x) 152 | 153 | x = 5 154 | f(x) 155 | print(x) 156 | ``` 157 | 158 | - Nesse caso temos diferentes objetos `x` 159 | 160 | ```python 161 | def g(y): 162 | print(x) 163 | print(x+1) 164 | 165 | x = 5 166 | g(x) 167 | print(x) 168 | ``` 169 | 170 | - `x` dentro de `x` é capturado do mesmo escopo que chamou a função `g` 171 | 172 | ```python 173 | def h(y): 174 | x += 1 175 | 176 | x = 5 177 | h(x) 178 | print(x) 179 | ``` 180 | 181 | --------------------------------------- 182 | 183 | ## *args & **kwargs 184 | 185 | As variáveis mágicas `*args` e `**kwargs` são normalmente usadas em definições de funções, elas nos permitem passar um número variável de argumentos para uma função. Variável nesse caso significa que não sabemos de antemão quantos argumentos vamos receber, então nesse caso utilizamos `*args` e `**kwargs`. 186 | 187 | ### *args 188 | 189 | `*args` é usado para enviar uma variável que **não tenha** palavras-chave, veja um exemplo: 190 | 191 | ```python 192 | def soma(*args): 193 | total = 0 194 | for num in args: 195 | total += num 196 | return total 197 | 198 | print(soma(2,3,4,6)) # 15 199 | print(soma(2,3,4,6,5,5,5,1,2)) # 32 200 | print(soma(2,3)) # 5 201 | ``` 202 | 203 | ### **kwargs 204 | 205 | `**kwargs` nos permite passarmos variáveis com **palavras-chave** como argumento, veja exemplos: 206 | 207 | ```python 208 | def pessoa(**kwargs): 209 | print(kwargs) 210 | for nome, idade in kwargs.items(): 211 | print(f'{nome} tem atualmente {idade} anos de idade') 212 | 213 | pessoa(gabriel='33', rafael='47', daniel='22') 214 | 215 | # {'gabriel': '33', 'rafael': '47', 'daniel': '22'} 216 | # gabriel tem atualmente 33 anos de idade 217 | # rafael tem atualmente 47 anos de idade 218 | # daniel tem atualmente 22 anos de idade 219 | ``` 220 | 221 | --------------------------------------- 222 | 223 | ## Recursão 224 | 225 | **'Recursividade'** é um termo usado de maneira mais geral para descrever o processo de repetição de um objeto de um jeito similar ao que já fora mostrado. Um bom exemplo disso são as imagens repetidas que aparecem quando dois espelhos são apontados um para o outro. 226 | 227 | Outro grande exemplo seria O Triângulo de Sierpinski - também chamado de Junta de Sierpinski - é uma figura geométrica obtida através de um processo **recursivo**. Ele é uma das formas elementares da geometria fractal por apresentar algumas propriedades, tais como: ter tantos pontos como o do conjunto dos números reais; ter área igual a zero; ser auto-semelhante (uma parte sua é idêntica ao todo); não perder a sua definição inicial à medida que é ampliado. Foi primeiramente descrito em 1915 por Waclaw Sierpinski (1882 - 1969), matemático polonês. 228 | 229 | Imagem do Triângulo de Sierpinski: 230 | ![alt text](https://upload.wikimedia.org/wikipedia/commons/b/b7/SierpinskiTriangle.PNG "Triângulo de Sierpinski") 231 | 232 | Pensando de forma **computacional** 233 | 234 | - Algoritmicamente falando, **Recursão** Uma maneira de desenvolver soluções para problemas através de *divide-and-conquer* ou *decrease-and-conquer* 235 | - Reduz o problema para versões simplificadas do mesmo problema 236 | 237 | - Semanticamente: Uma técnica de programação onde a função **chama a si mesmo** 238 | - Em Programação, o objetivo é não ter recursão infinita 239 | - Deve ter **1 ou mais casos bases** que são fáceis de resolver 240 | - Deve resolver o mesmo problema em algum outro input com o objetivo de simplificar o input do problema maior 241 | 242 | --------------------------------------- 243 | 244 | ## Recursão em Python 245 | 246 | Nós sabemos que em **Python** é possível uma **função** chamar outras **funções**, inclusive é possível que uma função chame ela mesma, esses tipos de constructos são chamados de **funções recursivas**. 247 | 248 | A seguir temos o exemplo de uma função que descobre o fatorial de um inteiro. Fatorial de um número é produto de todos inteiros de 1 até esse número. Por exemplo, o fatorial de 5 (denotado por 5!) é 1x2x3x4x5 = 120 249 | 250 | Exemplo de uma **função recursiva**: 251 | 252 | ```python 253 | def fatorial(x): 254 | """ 255 | Essa é uma função recursiva 256 | Ela calcula o fatorial de um número inteiro 257 | """ 258 | 259 | if x == 1: 260 | return 1 261 | else: 262 | return (x * fatorial(x - 1)) 263 | 264 | y = 4 265 | z = 10 266 | print("O fatorial de {0} é {1}".format(y,fatorial(y))) # O fatorial de 4 é 24 267 | print("O fatorial de {0} é {1}".format(z,fatorial(z))) # O fatorial de 7 é 3628800 268 | ``` 269 | 270 | No exemplo acima **fatorial()** é considerada uma **função recursiva**, pois chama a ela mesma. Quando nós chamamos essa função com um inteiro positivo, ela chamará recursivamente ela mesma diminuindo o número. Para entendermos melhor, veja 271 | 272 | ```python 273 | fatorial(4) # Primeira chamada com 4 274 | 4 * fatorial(3) # Segunda chamada com 3 275 | 4 * 3 * fatorial(2) # Terceira chamada com 2 276 | 4 * 3 * 2 * fatorial(1) # Quarta chamada com 1 277 | 4 * 3 * 2 * 1 # Retorno da quarta chamada, uma vez que y = 1 278 | 4 * 3 * 2 # Retorno da terceira chamada 279 | 4 * 6 # Retorno da segunda chamada 280 | 24 # Retorno da primeira chamada 281 | ``` 282 | 283 | Como podem ver, nossa recursão acaba quando o valor de **y** reduz a **1**, essa é considerada a **condição base**. Toda recursão deve ter uma condição base que para a recursão ou a função ficará chamando-a eternamente. 284 | 285 | --------------------------------------- 286 | 287 | ## Recursão com Múltiplos Casos Base 288 | 289 | - Números Fibonacci 290 | - Leonardo de Pisa (também conhecido como Fibonacci) modelou o seguinte desafio: 291 | - Pares de coelhos recém-nascidos (um macho e uma fêmea) são colocados em um curral 292 | - Coelhos se acasalam na idade de um mês 293 | - Coelhos tem um mês de período de gestação 294 | - Assumindo que o coelho nunca morre, a fêmea sempre produz um novo par (um macho e uma fêmea) a cada mês a partir do segundo mês 295 | - Quantos coelhos fêmeas estão lá no final do ano? 296 | 297 | ### Fibonacci 298 | 299 | 1. Depois de um mês (chama ele de 0) - 1 fêmea 300 | 2. Depois do segundo mês, ainda 1 fêmea (agora grávida) 301 | 3. Depois do terceiro, duas fêmeas, uma grávida, uma não 302 | 4. Em geral, fêmeas(n) = fêmeas(n-1) + fêmeas(n-2) 303 | - Cada fêmea viva no mês n-2 irá produzir uma fêmea no mês n 304 | - Estes podem ser adicionados aqueles vivos no mês n-1 para obter total vivos no mês n 305 | 306 | - Casos Base: 307 | - Femeas(0) = 1 308 | - Femeas(1) = 1 309 | - Caso Recursivo 310 | - Femeas(n) = Femeas(n-1) + Femeas(n-2) 311 | 312 | ```python 313 | def fib(x): 314 | """ 315 | Assume x como inteiro >= 0 316 | Retorna o Fibonacii de x 317 | """ 318 | if x == 0 or x == 1: 319 | return 1 320 | else: 321 | return fib(x-1) + fib(x-2) 322 | ``` 323 | 324 | --------------------------------------- 325 | 326 | ## Vantagens e Desvantagens 327 | 328 | **Vantagens** da Recursão: 329 | 330 | 1. Funções recursivas tornam o código limpo e elegante 331 | 2. Uma tarefa complexa pode ser quebrada em sub-problemas usando a recursão 332 | 3. Gerar sequências é mais fácil com recursão 333 | 334 | **Desvantagens** da Recursão: 335 | 336 | 1. As vezes a lógica por trás dela pode ser complexa de entender 337 | 2. Chamadas recursivas são custosas e ineficientes e podem nos custar muita memória e tempo! 338 | 3. Funções recursivas são mais difíceis de debugar (processo de encontrar e reduzir defeitos de um programa). 339 | 340 | Por fim, entendemos que as funções são um tema essencial e fundamental para a programação, elas são capazes de facilitar muito a vida dos programadores através da **abstração**, tornando os códigos muito mais bonitos, modulares e fáceis de entender. O código ainda pode ser utilizados muitas vezes e precisa ser **debuggado/testado** apenas uma vez. 341 | 342 | Cheque a **[documentação](https://docs.python.org/3/library/functions.html)** oficial do Python para conhecer todas as funções construídas no **interpretador** Python. 343 | 344 | **Próximo Capítulo**: [Expressões Lambda](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/17.Lambda.md) 345 | -------------------------------------------------------------------------------- /Capitulos/21.DataTempo.md: -------------------------------------------------------------------------------- 1 | # Data e Tempo 2 | 3 | O módulo **datetime** nos fornece **classes** para manipularmos **data** e **tempo** de maneiras simples e complexas. Enquanto que operações aritméticas de data e tempo são aceitas, o foco da implementação é em uma eficiente extração de membros para formatação de output e manipulação. 4 | 5 | ```python 6 | from datetime import date 7 | 8 | agora = date.today() 9 | print(agora) # 2018-10-27 10 | ``` 11 | 12 | Podemos também utilizar dessa forma 13 | 14 | ```python 15 | import datetime 16 | 17 | d = datetime.datetime.now() 18 | print(d) # 2018-10-27 20:28:24.463585 19 | ``` 20 | 21 | Nesse caso a data contém ano, mês, dia, hora, minuto, segundo e microsegundo. O módulo **datetime** tem diversos métodos para retornar informação sobre o objeto data. Por exemplo: 22 | 23 | ```python 24 | print(d.year) 25 | print(d.strftime("%A")) 26 | ``` 27 | 28 | --------------------------------------- 29 | 30 | ## Criando Objetos de Data 31 | 32 | Para criarmos uma data podemos usar o construtor **datetime()** do módulo **datetime**. A classe **datetime()** espera que passemos três parâmetros para criarmos uma data, são eles: ano, mês e dia. 33 | 34 | ```python 35 | import datetime 36 | 37 | d = datetime.date(2016, 5, 20) 38 | print(d) # 2016-05-20 39 | ``` 40 | 41 | A classe **datetime()** também pode receber parâmetros para tempo e timezone (hora, minuto, segundo, microsegundo, tzone), porém eles são opcionais. 42 | 43 | Obtendo o dia de hoje através do método `date.today()` 44 | 45 | ```python 46 | hoje = datetime.date.today() 47 | print(hoje) # 2019-05-10 48 | print(hoje.year) # 2019 49 | print(hoje.day) # 10 50 | 51 | # Segunda 0 Domingo 6 52 | print(hoje.weekday()) # 4 53 | # Segunda 1 Domingo 7 54 | print(hoje.isoweekday()) # 5 55 | ``` 56 | 57 | Criando um objeto **[timedelta](https://docs.python.org/3/library/datetime.html#timedelta-objects)** através do do construtor `timedelta()` 58 | 59 | ```python 60 | tdelta = datetime.timedelta(days=7) 61 | ``` 62 | 63 | Podemos somar o **timedelta** com o nosso dia de hoje para obter uma nova data 64 | 65 | ```python 66 | print(hoje + tdelta) # 2019-05-17 67 | ``` 68 | 69 | Também é possível subtrair o **timedelta** 70 | 71 | ```python 72 | print(hoje - tdelta) 73 | ``` 74 | 75 | O construtor **time()** nos permite criar **[Objetos time](https://docs.python.org/3/library/datetime.html#datetime.time)** 76 | 77 | ```python 78 | t = datetime.time(9, 30, 45, 10000) 79 | 80 | # Imprime a hora 81 | print(t.hour) # 9 82 | # Imprime os minutos 83 | print(t.minute) # 30 84 | # Imprime os segundos 85 | print(t.second) # 45 86 | # Imprime os microsegundos 87 | print(t.microsecond) # 10000 88 | ``` 89 | 90 | É possível combinar data e tempo para uma construção mais precisa 91 | 92 | ```python 93 | t2 = datetime.datetime(2019, 7, 26, 12, 30, 45, 100000) 94 | print(t2) # 2019-07-26 12:30:45.100000 95 | print(t2.date()) # 2019-07-26 96 | print(t2.time()) # 12:30:45.100000 97 | ``` 98 | 99 | Através dos métodos **today()**, **now()** e **utcnow()** podemos obter a data do momento atual 100 | 101 | ```python 102 | data_hoje = datetime.datetime.today() 103 | data_agora = datetime.datetime.now() 104 | data_utc_agora = datetime.datetime.utcnow() 105 | 106 | print(data_hoje) # 2019-05-10 10:52:23.867904 107 | print(data_agora) # 2019-05-10 10:52:23.867974 108 | print(data_utc_agora) # 2019-05-10 13:52:23.868025 109 | ``` 110 | 111 | O Método **strftime()** 112 | 113 | O objeto **datetime** possui um método para formatarmos objetos de data em strings legíveis, este método é chamado de **strftime()** e ele recebe um parâmetro **format** que especificará o formato no qual a string será retornada 114 | 115 | ```python 116 | import datetime 117 | 118 | d = datetime.datetime(2013, 4, 11) 119 | # strftime - Converte Datetime para String 120 | print(d.strftime("%B")) # April 121 | ``` 122 | 123 | Já o método **strptime()** é capaz de converter uma string para um objeto **datetime** 124 | 125 | ```python 126 | # strptime - Converte String para Datetime 127 | data_string = 'May 10 2019' 128 | data_convertida = datetime.datetime.strptime(data_string, '%B %d %Y') 129 | print(data_convertida) # 2019-05-10 00:00:00 130 | ``` 131 | 132 | A seguir temos uma referência de todos os formatos legais que podemos utilizar 133 | 134 | | Formato | Descrição | Exemplo | 135 | |---------|:------------------------------------------------------------------------:|--------------------------:| 136 | | %a | dia da semana, versão pequena | Wed | 137 | | %A | dia de semana, versão completa | Wednesday | 138 | | %w | dia de semana como número 0-6, sendo 0 domingo | 3 | 139 | | %d | Dia do mês 01-31 | 21 | 140 | | %b | Nome do mês, versão pequena | Dec | 141 | | %B | Nome do mês, versão completa | December | 142 | | %m | Mês como número, 01-12 | 12 | 143 | | %y | Ano, versão pequena, sem século | 18 | 144 | | %Y | Ano, versão completa | 2018 | 145 | | %H | Hora 00-23 | 17 | 146 | | %I | Hora 00-12 | 05 | 147 | | %p | AM/PM | PM | 148 | | %M | Minuto 00-59 | 41 | 149 | | %S | Segundo 00-59 | 08 | 150 | | %f | Microsegundo 000000-999999 | 548513 | 151 | | %z | UTC offset | +0100 | 152 | | %Z | Zone de tempo | CST | 153 | | %j | Número do dia do ano 001-366 | 365 | 154 | | %U | Número da semana do ano, Domingo sendo o primeiro dia da semana, 00-53 | 52 | 155 | | %W | Número da semana do ano, Segunda sendo o primeiro dia da semana, 00-53 | 52 | 156 | | %c | Versão local de data e tempo | Mon Dec 31 17:41:00 2018 | 157 | | %x | Versão local de data | 12/31/18 | 158 | | %X | Versão local de tempo | 17:41:00 | 159 | | %% | Um sinal de % | % | 160 | 161 | --------------------------------------- 162 | 163 | ## Calendário 164 | 165 | Outro módulo muito legal que **Python** nos proporciona é o **calendar**, que nos fornece uma grande variedade de métodos para testarmos diversos calendários com ano e mês. 166 | 167 | ```python 168 | import calendar 169 | 170 | cal = calendar.month(2014, 2) 171 | print(cal) 172 | 173 | # February 2014 174 | # Mo Tu We Th Fr Sa Su 175 | # 1 2 176 | # 3 4 5 6 7 8 9 177 | # 10 11 12 13 14 15 16 178 | # 17 18 19 20 21 22 23 179 | # 24 25 26 27 28 180 | ``` 181 | 182 | ### Imprimindo um Calendário para um Ano Específico 183 | 184 | Podemos utilizar a função **calendar.calendar()** para imprimirmos o calendário completo para um determinado ano. 185 | 186 | ```python 187 | # A função calendar recebe como parâmetro: 188 | 189 | ## ano 190 | ## comprimento da coluna data 191 | ## número de linhas por semana 192 | ## número de espaços entre a coluna mês 193 | ## número de colunas 194 | print(calendar.calendar(2019, 2, 2, 6, 3)) 195 | ``` 196 | 197 | Nos é trazido como output: 198 | 199 | ``` 200 | January February March 201 | 202 | Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 203 | 204 | 1 2 3 4 5 6 1 2 3 1 2 3 205 | 206 | 7 8 9 10 11 12 13 4 5 6 7 8 9 10 4 5 6 7 8 9 10 207 | 208 | 14 15 16 17 18 19 20 11 12 13 14 15 16 17 11 12 13 14 15 16 17 209 | 210 | 21 22 23 24 25 26 27 18 19 20 21 22 23 24 18 19 20 21 22 23 24 211 | 212 | 28 29 30 31 25 26 27 28 25 26 27 28 29 30 31 213 | 214 | 215 | 216 | April May June 217 | 218 | Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 219 | 220 | 1 2 3 4 5 6 7 1 2 3 4 5 1 2 221 | 222 | 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9 223 | 224 | 15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16 225 | 226 | 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 227 | 228 | 29 30 27 28 29 30 31 24 25 26 27 28 29 30 229 | 230 | 231 | 232 | July August September 233 | 234 | Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 235 | 236 | 1 2 3 4 5 6 7 1 2 3 4 1 237 | 238 | 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8 239 | 240 | 15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15 241 | 242 | 22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22 243 | 244 | 29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29 245 | 246 | 30 247 | 248 | 249 | 250 | October November December 251 | 252 | Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su 253 | 254 | 1 2 3 4 5 6 1 2 3 1 255 | 256 | 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8 257 | 258 | 14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15 259 | 260 | 21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22 261 | 262 | 28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29 263 | 264 | 30 31 265 | ``` 266 | 267 | Checando por um Ano Bissexto 268 | 269 | A função **isleap()** checa se um ano é bissexto ou não. Para utilizarmos ela é necessário passarmos um ano como argumento e ela nos retornará `True` se ele for bissexto e `False` caso não seja. 270 | 271 | Vamos checar o ano de 2017 272 | 273 | ```python 274 | print(calendar.isleap(2017)) # False 275 | ``` 276 | 277 | Retornando o Dia da Semana 278 | 279 | O método **weekday()** recebe três argumentos: **ano**, **mês** e **dia** e nos retorna o dia da semana como índice **0-6** em que: 280 | 281 | - 0 representa segunda-feira 282 | - 1 representa terça-feira 283 | - 2 representa quarta-feira 284 | - 3 representa quinta-feira 285 | - 4 representa sexta-feira 286 | - 5 representa sábado 287 | - 6 representa domingo 288 | 289 | ```python 290 | print(calendar.weekday(2019,8,19)) # 0 291 | ``` 292 | 293 | --------------------------------------- 294 | 295 | ## Biblioteca pytz 296 | 297 | A **[Biblioteca pytz](http://pytz.sourceforge.net/)** nos permite a execução de cálculos de **[timezone](https://www.timeanddate.com/time/map/)**. Para obtermos a biblioteca pytz é necessário que façamos sua instalação através do **pip** ou **pipenv** 298 | 299 | ``` 300 | pip install pytz 301 | ``` 302 | 303 | ``` 304 | pipenv install pytz 305 | ``` 306 | 307 | Criando um data através do método **datetime()** e passando como parâmetro a **timezone** 308 | 309 | ```python 310 | data_tz = datetime.datetime(2019, 7, 20, 12, 30, 45, tzinfo=pytz.UTC) 311 | print(data_tz) # 2019-07-20 12:30:45+00:00 312 | ``` 313 | 314 | Obtendo a data e tempo de agora com a zona de tempo 315 | 316 | ```python 317 | data_agora_tz = datetime.datetime.now(tz=pytz.UTC) 318 | print(data_agora_tz) # 2019-05-10 14:04:31.208341+00:00 319 | ``` 320 | 321 | Podemos converter para uma outra zona de tempo, nesse caso estamos trocando para 'America/Sao_Paulo' 322 | 323 | ```python 324 | dt_conversao = data_agora_tz.astimezone(pytz.timezone('America/Sao_Paulo')) 325 | print(dt_conversao) # 2019-05-10 08:04:31.208341-06:00 326 | ``` 327 | 328 | Para obtermos todas as zonas de tempo disponíveis, podemos percorrê-las com o loop for 329 | 330 | ```python 331 | for tz in pytz.all_timezones: 332 | print(tz) 333 | ``` 334 | 335 | Que nos traz como resultado: 336 | 337 | ``` 338 | Africa/Abidjan 339 | Africa/Accra 340 | Africa/Addis_Ababa 341 | Africa/Algiers 342 | ... 343 | US/Samoa 344 | UTC 345 | Universal 346 | W-SU 347 | WET 348 | Zulu 349 | ``` 350 | 351 | --------------------------------------- 352 | 353 | Com este rápido estudo, podemos concluir que **Python** nos traz grandes possibilidades de manipularmos data e tempo, que são aspectos bastante importantes da programação e computação. 354 | 355 | **Próximo Capítulo**: [Classes e Objetos](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/22.ClassesObjetos.md) 356 | -------------------------------------------------------------------------------- /Capitulos/19.InputOutputArquivos.md: -------------------------------------------------------------------------------- 1 | # Input & Output de Arquivos 2 | 3 | A ideia desse artigo é nos aprofundarmos no assunto sobre os **arquivos** e as operações que podemos executar neles através do **Python**, mais especificamente *abrindo arquivos*, *lendo arquivos* e *escrevendo em arquivos*, como *fechá-los* e diversos métodos importantes que devemos conhecer. 4 | 5 | ## O que é um arquivo? 6 | 7 | Arquivo é uma localização em disco com um nome, que tem como objetivo guardar informação. É usado para guardarmos dados na memória não-volátil (disco-rígido), uma vez que a memória de acesso randômico (RAM) é volátil e perde todos os dados quando desligamos o nosso computador, para isso trabalhamos com os arquivos, de forma a fazer com que nossos dados **persistam em disco**. 8 | 9 | Quando nós queremos ler um arquivo ou escrever nele, precisamos abrí-lo antes, quando estivermos finalizado, precisamos fechá-lo, para que assim os recursos que estão ligados com o arquivo, sejam liberados, sendo assim, a operação com arquivos funciona da seguinte forma: 10 | 11 | - Abrir o arquivo 12 | - Ler ou escrever (operação desejada) 13 | - Fechar o arquivo 14 | 15 | --------------------------------------- 16 | 17 | ## Como abrir um arquivo? 18 | 19 | **Python** tem uma função construída que se chama **open()**, ela abre arquivos. Essa função retorna um **file object** que nos possibilita manipular o arquivo de várias maneiras, por exemplo 20 | 21 | ```python 22 | f = open("teste.txt") # Abrindo arquivo no diretório atual 23 | f = open("/home/usuario/teste.txt") # Abrindo o arquivo especificando o seu caminho completo (full path) 24 | ``` 25 | 26 | Podemos especificar o modo quando abrindo o arquivo, o modo nos permite especificar se queremos ler **'r'**, escrever **'w'** ou append **'a'**, que seria o ato de adicionar textos no arquivo sem destruir o que já está previamente nele. É possível também especificar se queremos abrir o arquivo no modo texto ou no modo binário. O padrão é o modo leitura, nesse modo nós recebemos strings ao ler do arquivo. No caso do modo binário ele nos retorna **bytes**, esse modo é interessante caso queiramos lidar com arquivos que não sejam textos, como por exemplo imagens e arquivos executáveis. 27 | 28 | ## Modos de Abrir Arquivo 29 | 30 | | Modo | Nome | Descrição | 31 | |------|-------------|----------------------------------------------------------------------------------| 32 | | "r" | Ler | Padrão, abre um arquivo para leitura, ocorrerá um erro caso o arquivo não exista | 33 | | "a" | Append | Abre um arquivo para appending, cria ele caso este não exista | 34 | | "w" | Escreve | Abre um arquivo para escrita, cria ele caso este não exista | 35 | | "x" | Cria | Cria o arquivo especificado, retorna um erro se o arquivo já existir | 36 | | "+" | Atualização | Abre o arquivo para atualização (ler ou escrever) | 37 | 38 | Além disso poderemos especificar se lidaremos em modo binário ou texto 39 | 40 | | Modo | Nome | Descrição | 41 | |------|---------|--------------| 42 | | "t" | Texto | Modo padrão | 43 | | "b" | Binário | Modo binário | 44 | 45 | ### Exemplos 46 | 47 | ```python 48 | f = open("teste.txt") # O mesmo que 'r' ou 'rt' 49 | f = open("teste.txt", "w") # escrever no modo texto 50 | f = open("img.png", 'r+b') # ler e escrever no modo binário 51 | ``` 52 | 53 | ### Fechando um Arquivo usando Python 54 | 55 | Uma vez que terminamos todas as operações no arquivo, é necessário que fechemos ele corretamente, fechando ele teremos recursos liberados, e para isso usaremos o método **close()**. É importante lembrarmos que **Python** tem um garbage collector (coletor de lixo) que limpa objetos não referenciados, mas mesmo assim é importante que fechemos os nossos arquivos por questões de boas práticas e segurança 56 | 57 | ```python 58 | f = open("teste.txt", enconding = 'utf-8') # Perceba que especificamos o modo de encoding para 'utf-8' para evitarmos conflitos, uma vez que cada sistema tem um modo padrão de codificar, sendo windows o 'cp1252' e linux 'utf-8' 59 | f.close() # Fecha o arquivo 60 | ``` 61 | 62 | Dessa forma não é tão seguro, pois caso ocorra algum problema durante a operação no arquivo, o código sai sem que o arquivo seja fechado de maneira adequada. Para isso, temos uma forma mais segura, usando as palavras-chave **try** e **finally** 63 | 64 | ```python 65 | try: 66 | f = open("teste.txt", encoding = 'utf-8') 67 | finally: 68 | f.close() 69 | ``` 70 | 71 | Dessa forma nós garantimos que o arquivo seja fechado de maneira adequada, mesmo que algum erro ocorra. Outra maneira de contornarmos essa situação seria utilizando a palavra-chave **with**, que nos assegura que o arquivo é fechado quando o bloco de código dentro de **with** é finalizado, dessa forma não precisamos mais usar **close()** explicitamente, pois é feito internamente por nós 72 | 73 | ```python 74 | with open("teste.txt", encoding = 'utf-8') as f: 75 | ``` 76 | 77 | ### Escrevendo em Arquivos 78 | 79 | Para escrevermos em um arquivo é muito simples, só precisamos especificar o modo, seja ele **'w'** para escrever, **'a'** para append ou **'x'** para criação exclusiva, fique atento ao usar o modo **'w'**, pois ele pode sobrescrever um arquivo caso ele já exista. Para escrevermos uma string ou sequencias de bytes (para arquivos binários) usamos o método **write()**, este que retorna o número de caracteres escritos no arquivo 80 | 81 | ```python 82 | with open("teste.txt", 'w', encoding = 'utf-8') as f: 83 | f.write("Estamos escrevendo no arquivo\n") 84 | f.write("Outra linha escrita no arquivo\n") 85 | ``` 86 | 87 | Esse programa irá criar um novo arquivo de nome **teste.txt** caso ele não exista, se já existir será sobrescrito. Perceba que colocamos o **\n** para que possamos obter novas linhas. 88 | 89 | ### Lendo Arquivos 90 | 91 | Para lermos um arquivo nós devemos abrí-lo no modo de leitura, existem diversos métodos para isso, como o **read(size)**, onde **size** é o tamanho, caso não especificarmos **size**, ele lerá e retornará até o fim do arquivo 92 | 93 | ```python 94 | f = open("teste.txt", 'r', encoding = 'utf-8') 95 | f.read(4) # Lê os primeiro 4 dados 96 | f.read(4) # Lê mais 4 dados 97 | f.read() # Lê o resto do arquivo 98 | ``` 99 | 100 | Podemos ver que o método **read()** retorna as novas linhas como **\n**. Uma vez que o final do arquivo é alcançado, nós recebemos uma string vazia se continuarmos tentando ler. Nós podemos alterar o **cursor(posição)** do arquivo atual usando o método **seek()**, além disso, o método **tell()** retorna a nossa posição atual (em números de bytes). 101 | 102 | Outra forma de lermos arquivos é utilizando o método **readline()**, que lerá cada linha individualmente. Esse método lerá até a nova linha, incluindo o caracter de nova linha **\n** 103 | 104 | ```python 105 | f.readline() # 'Estamos escrevendo no arquivo\n' 106 | f.readline() # 'Outra linha escrita no arquivo\n' 107 | ``` 108 | 109 | Por fim temos o método **readlines()** que retorna uma lista das linhas restantes de todo o arquivo. Todos esses métodos de leitura retornam válores vazios quando alcançamos o fim do arquivo **(EOF)**. 110 | 111 | ```python 112 | f.readlines() # ['Estamos escrevendo no arquivo\n', 'Outra linha escrita no arquivo\n'] 113 | ``` 114 | 115 | ### Lista completa de métodos de arquivo em Python 116 | 117 | | Métodos | Descrição | 118 | |--------------|-----------------------------------------------------------------------------------------| 119 | | close() | Fecha um Arquivo | 120 | | detach() | Retorna o fluxo bruto separado do buffer | 121 | | fileno() | Retorna um número que representa o fluxo, através da perspectiva do Sistema Operacional | 122 | | flush() | Libera o buffer interno | 123 | | isatty() | Retorna se o fluxo do arquivo é interactivo ou não | 124 | | read() | Retorna o conteúdo do Arquivo | 125 | | readable() | Retorna se o fluxo do arquivo pode ser lido ou não | 126 | | readline() | Retorna uma linha do Arquivo | 127 | | readlines() | Retorna uma lista de linhas do Arquivo | 128 | | seek() | Muda a posição do Arquivo | 129 | | seekable() | Retorna se o Arquivo nos permite mudar a posição do Arquivo | 130 | | tell() | Retorna a posição do Arquivo atual | 131 | | truncate() | Altera o tamanho do Arquivo para um tamanho especificado | 132 | | writable() | Retorna se o Arquivo pode escrito ou não | 133 | | write() | Escreve a string especificada em um Arquivo | 134 | | writelines() | Escreve uma lista de strings em um Arquivo | 135 | 136 | --------------------------------------- 137 | 138 | ## Arquivos CSV 139 | 140 | Um arquivo **[CSV (Comma Separated Values)](https://www.computerhope.com/issues/ch001356.htm)** é um tipo de arquivo de texto simples que usa uma estrutura específica para organizar dados tabulares. Por ser um arquivo de texto simples, ele pode conter apenas dados de texto reais, em outras palavras, caracteres ASCII ou Unicode imprimíveis. 141 | 142 | A estrutura de um arquivo CSV é dada pelo seu nome. Normalmente, arquivos CSV utilizam **vírgula** para separar cada valor específico de dados. Vejamos o exemplo do arquivo `livros.csv` abaixo para entendermos melhor 143 | 144 | ``` 145 | Title,Author,Genre,Height,Publisher 146 | Fundamentals of Wavelets,"Goswami, Jaideva",signal_processing,228,Wiley 147 | Data Smart,"Foreman, John",data_science,235,Wiley 148 | God Created the Integers,"Hawking, Stephen",mathematics,197,Penguin 149 | Superfreakonomics,"Dubner, Stephen",economics,179,HarperCollins 150 | Orientalism,"Said, Edward",history,197,Penguin 151 | "Nature of Statistical Learning Theory, The","Vapnik, Vladimir",data_science,230,Springer 152 | Integration of the Indian States,"Menon, V P",history,217,Orient Blackswan 153 | "Drunkard's Walk, The","Mlodinow, Leonard",science,197,Penguin 154 | Image Processing & Mathematical Morphology,"Shih, Frank",signal_processing,241,CRC 155 | ``` 156 | 157 | Perceba que cada valor de dados é separado por uma **vírgula**. Normalmente a primeira linha identifica cada valor dos dados, em outras palavras, o nome da coluna dos dados. De modo geral, o caracter separador é chamado de **delimitador** e a vírgula não é o único utilizado. Outros delimitadores includem os caracteres **tab**(\t), **dois pontos**(:) e **ponto e vírgula**(;). Para acessarmos os dados de um arquivo CSV de forma correta é necessário que saibamos com qual delimitador estamos trabalhando. 158 | 159 | ### Lendo Arquivos CSV 160 | 161 | A **[biblioteca csv](https://docs.python.org/3/library/csv.html)** nos fornece a funcionalidade de lermos arquivos CSV e também escrever. Desenvolvida para trabalharmos diretamente com arquivos CSV gerados por Excel, pode ser facilmente adaptável para trabalharmos com uma variedade de formatos CSV. 162 | 163 | #### Método reader 164 | 165 | O Método `reader()` nos retorna um objeto `_csv.reader` iterável que podemos percorrer através de um **for loop** 166 | 167 | ```python 168 | import csv 169 | 170 | with open('livros.csv', newline='') as csv_file: 171 | csv_reader = csv.reader(csv_file) 172 | for linha in csv_reader: 173 | print(f"{linha[0]},{linha[1]}") 174 | ``` 175 | 176 | Nos é retornado o resultado: 177 | 178 | ``` 179 | Title,Author 180 | Fundamentals of Wavelets,Goswami, Jaideva 181 | Data Smart,Foreman, John 182 | God Created the Integers,Hawking, Stephen 183 | Superfreakonomics,Dubner, Stephen 184 | Orientalism,Said, Edward 185 | Nature of Statistical Learning Theory, The,Vapnik, Vladimir 186 | Integration of the Indian States,Menon, V P 187 | Drunkard's Walk, The,Mlodinow, Leonard 188 | Image Processing & Mathematical Morphology,Shih, Frank 189 | ``` 190 | 191 | Perceba que estamos imprimindo apenas as duas primeiras colunas **(Title e Autor)** 192 | 193 | #### Método DictReader 194 | 195 | O Método `DictReader()` nos retorna um objeto `csv.DictReader` que podemos iterar e percorrer os valores através de um **for loop** 196 | 197 | ```python 198 | import csv 199 | 200 | with open('book.csv', newline='') as csv_file: 201 | csv_reader = csv.DictReader(csv_file) 202 | for linha in csv_reader: 203 | print(f"{linha['Title']} | {linha['Author']} | {linha['Genre']} | {linha['Publisher']}") 204 | ``` 205 | 206 | Nos é retornado o seguinte resultado: 207 | 208 | ``` 209 | Fundamentals of Wavelets | Goswami, Jaideva | signal_processing | Wiley 210 | Data Smart | Foreman, John | data_science | Wiley 211 | God Created the Integers | Hawking, Stephen | mathematics | Penguin 212 | Superfreakonomics | Dubner, Stephen | economics | HarperCollins 213 | Orientalism | Said, Edward | history | Penguin 214 | Nature of Statistical Learning Theory, The | Vapnik, Vladimir | data_science | Springer 215 | Integration of the Indian States | Menon, V P | history | Orient Blackswan 216 | Drunkard's Walk, The | Mlodinow, Leonard | science | Penguin 217 | Image Processing & Mathematical Morphology | Shih, Frank | signal_processing | CRC 218 | ``` 219 | 220 | ### Escrevendo em Arquivos CSV 221 | 222 | Nós podemos escrever em um arquivo CSV utilizando o objeto **writer** ou **DictWriter** e o método **write_row()**. Vejamos um exemplo. 223 | 224 | ```python 225 | import csv 226 | 227 | with open('livros.csv', newline='') as csv_file: 228 | csv_reader = csv.DictReader(csv_file) 229 | 230 | with open('livros_novos.csv', 'w') as novo_arquivo: 231 | fieldnames = ['Title', 'Author', 'Genre'] 232 | csv_writer = csv.DictWriter(novo_arquivo, fieldnames=fieldnames, delimiter=';') 233 | csv_writer.writeheader() 234 | 235 | for linha in csv_reader: 236 | del linha['Height'] 237 | del linha['Publisher'] 238 | csv_writer.writerow(linha) 239 | ``` 240 | 241 | - A variável `fieldnames` especifica as colunas que vamos utilizar em nosso novo arquivo 242 | - O construtor `DictWriter` recebe como parâmetro nosso **novo_arquivo**, os `fieldnames` e o delimitador que nesse caso estamos utilizando (;). 243 | - O método `writeheader()` escreve no arquivo `livros_novos.csv` o nosso novo cabeçalho 244 | - Através do **for** nós percorremos os dados do arquivo `livros.csv` e deletamos as colunas **Height** e **Publisher** usando a palavra-chave `del` 245 | - Finalizamos escrevendo no novo arquivo `livros_novos.csv` através do método `writerow` 246 | 247 | Por fim, obtivemos um novo arquivo `livros_novos.csv` com o seguinte conteúdo: 248 | 249 | ``` 250 | Title;Author;Genre 251 | Fundamentals of Wavelets;Goswami, Jaideva;signal_processing 252 | Data Smart;Foreman, John;data_science 253 | God Created the Integers;Hawking, Stephen;mathematics 254 | Superfreakonomics;Dubner, Stephen;economics 255 | Orientalism;Said, Edward;history 256 | Nature of Statistical Learning Theory, The;Vapnik, Vladimir;data_science 257 | Integration of the Indian States;Menon, V P;history 258 | Drunkard's Walk, The;Mlodinow, Leonard;science 259 | Image Processing & Mathematical Morphology;Shih, Frank;signal_processing 260 | ``` 261 | 262 | --------------------------------------- 263 | 264 | Essa seria uma visão geral e introdução aos arquivos, saber manipulá-los é uma habilidade muito importante que devemos masterizar na nossa jornada. 265 | 266 | **Próximo Capítulo**: [Erros e Exceções](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/20.ErrosExce%C3%A7%C3%B5es.md) 267 | -------------------------------------------------------------------------------- /Capitulos/20.ErrosExceções.md: -------------------------------------------------------------------------------- 1 | # Erros e Exceções 2 | 3 | É muito comum encontrarmos erros ao escrevermos programas, o **Interpretador Python** é capaz de gerar **exceções** quando encontra erros, por exemplo uma **divisão por zero**. Um dos erros mais comuns de encontrarmos é o de síntaxe, quando não seguimos a estrutura correta da linguagem, chamamos esse erro de erro de síntaxe. Por exemplo: 4 | 5 | ```python 6 | if 2 > 1 7 | print("Dois maior do que um") 8 | 9 | # File "", line 1 10 | # if 2 >1 11 | # ^ 12 | # SyntaxError: invalid syntax 13 | ``` 14 | 15 | Perceba, que de propósito, omitimos o **:** e o interpretador nos retorna um erro de **síntaxe inválida** 16 | 17 | Além disso, erros também podem acontecer em **tempo de execução**, nesse caso eles são conhecidos como **exceções**. Eles ocorrem, por exemplo quando um arquivo que estamos tentando abrir não existe **(FileNotFoundError)**, dividir por zero **(ZeroDivisionError)**, módulos que tentamos importar e não são encontrados **(ImportError)** e uma série de outros. Quando esses erros em tempo de execução ocorrem, **Python** cria um objeto de exceção, e caso este não seja tratado de maneira própria, será impresso um **traceback** daquele erro e mais detalhes do motivo que ocorreu. 18 | 19 | ```python 20 | x = 1/0 21 | 22 | # Traceback (most recent call last): 23 | # File "", line 1, in 24 | # ZeroDivisionError: division by zero 25 | 26 | f = open("arquivo.txt") # Abrindo arquivo que não existe em nosso sistema de arquivos 27 | 28 | # Traceback (most recent call last): 29 | # File "", line 1, in 30 | # FileNotFoundError: [Errno 2] No such file or directory: 'arquivo.txt' 31 | ``` 32 | 33 | --------------------------------------- 34 | 35 | ## Exceções Construídas no Python 36 | 37 | Operações ilegais poderam gerar exceções, existem diversas exceções construídas em **Python** que são geradas quando erros correspondentes ocorrem, para vermos elas precisamos usar a função **locals()** 38 | 39 | ```python 40 | e = locals()['__builtins__'] 41 | print(dir(e)) 42 | print(type(e)) 43 | ``` 44 | 45 | Como podemos ver, essa função nos retornará um **** com exceções construídas, funções e atributos. Algumas das exceções mais comuns são listadas a seguir: 46 | 47 | | Exceção | Causa | 48 | |-----------------------|:-------------------------------------------------------------------------------------------------------------------------------:| 49 | | AssertionError | Surge quando o comando assert falha | 50 | | AttributeError | Surge quando uma atribuição ou referência falha | 51 | | EOFError | Surge quando a função input() chega na condição de fim de arquivo | 52 | | FloatingPointError | Surge quando uma operação de ponto flutuante falha | 53 | | GeneratorExit | Surge quando o método close() do gerador é chamado | 54 | | ImportError | Surge quando o módulo importado não é encontrado | 55 | | IndexError | Surge quando o índice de uma sequência está fora de alcance | 56 | | KeyError | Surge quando uma chave não é encontrada no dicionário | 57 | | KeyboardInterrupt | Surge quando um usuário aperta o botão de interrupção (CTRL + C ou delete) | 58 | | MemoryError | Surge quando acaba a memória de uma operação | 59 | | NameError | Surge quando uma variável não é encontrada no escopo local ou global | 60 | | NotImplementedError | Surge por métodos abstratos | 61 | | OSError | Surge quando alguma operação de sistema causa algum erro de sistema | 62 | | OverflowError | Surge quando uma operação aritmética é muito grande para ser representada | 63 | | ReferenceError | Surge quando um proxy de referência fraco é usado para acessar um garbage collected referente | 64 | | RuntimeError | Surge quando um erro não se encaixa em nenhuma outra categoria | 65 | | StopIteration | Surge pela função next() para indicar que não há mais itens para o iterador retornar | 66 | | SyntaxError | Surge pelo parser quando um erro de síntaxe ocorre | 67 | | IndentationError | Surge quando não indentamos nosso código | 68 | | TabError | Surge quando a indentação consiste de espaços e tabs impróprios | 69 | | SystemError | Surge quando o interpretador detecta um erro interno | 70 | | SystemExit | Surge pela função sys.exit() | 71 | | TypeError | Surge quando uma função ou operação é aplicada a um objeto de tipo incorreto | 72 | | UnboundLocalError | Surge quando uma referência é feita para uma variável local em uma função ou método, porém nenhum valor está preso à variável | 73 | | UnicodeError | Surge quando existe um erro relacionado a Unicode codificação ou decodificação | 74 | | UnicodeEncodeError | Surge quando um erro de codificação de Unicode ocorre | 75 | | UnicodeDecodeError | Surge quando um erro de decodificação de Unicode ocorre | 76 | | UnicodeTranslateError | Surge quando um erro de tradução de Unicode ocorre | 77 | | ValueError | Surge quando uma função pega um argumento de tipo correto, porém de valor impróprio | 78 | | ZeroDivisionError | Surge quando a segunda divisão ou módulo é zero | 79 | 80 | Além delas, podemos definir **nossas próprias exceções**, caso necessário, e para lidarmos com elas utilizamos as palavras-chave **try**, **except** e **finally**. 81 | 82 | | Palavra-chave | Descrição | 83 | |---------------|:-------------------------------------------------------------------------:| 84 | | try | nos permite testar um bloco de código por erros | 85 | | except | permite lidarmos com erros | 86 | | finally | permite executarmos códigos independente do resultado do try e do except | 87 | 88 | --------------------------------------- 89 | 90 | ## Lidando com Exceções 91 | 92 | ```python 93 | try: 94 | print(x) 95 | except: 96 | print("Uma exceção ocorreu") 97 | ``` 98 | 99 | O bloco **try** irá gerar uma exceção, uma vez que **x** não está definida, uma vez gerada, o bloco **except** é executado, caso não tivéssemos o bloco **try** o programa iria *crashar* e um erro surgiria. Podemos também definir diversos blocos de exceção. 100 | 101 | ```python 102 | try: 103 | print(x) 104 | except NameError: 105 | print("Variável x não está definida") 106 | except: 107 | print("Algum outro erro ocorreu") 108 | ``` 109 | 110 | O bloco **finally**, se especificado, será executado independente de surgir ou não um erro no **try** 111 | 112 | ```python 113 | try: 114 | print(x) 115 | except: 116 | print("Algum erro ocorreu") 117 | finally: 118 | print("O try e except foram finalizados") 119 | ``` 120 | 121 | ```python 122 | try: 123 | a = int(input('Diga-me um número: ')) 124 | b = int(input('Diga-me um outro número: ')) 125 | print(a/b) 126 | except: 127 | print('erro no input do usuário') 128 | ``` 129 | 130 | ### Lidando com Exceções Específicas 131 | 132 | Tenha claúsulas de **except** separadas para lidar com um tipo particular de exceção 133 | 134 | ```python 135 | try: 136 | a = int(input('Diga-me um número: ')) 137 | b = int(input('Diga-me um outro número: ')) 138 | print("a/b = ", a/b) 139 | print("a+b = ", a+b) 140 | except ValueError: # Só executa se esse erro surgir 141 | print('Não podemos converter para um número') 142 | except ZeroDivisionError: # Só executa se esse erro surgir 143 | print('Não podemos dividir por zero') 144 | except: # executa para todos os outros erros 145 | print('algo de muito errado aconteceu') 146 | ``` 147 | 148 | ### O que fazer com Exceções? 149 | 150 | - O que fazer quando encontrar um erro? 151 | 152 | - Falhar silenciosamente 153 | - Substituir valores padrão ou apenas continuar 154 | - Má ideia! usuários não obtem avisos 155 | 156 | - Retornar um valor erro 157 | - Qual valor escolher? 158 | - Complica o código tendo de checar por um valor especial 159 | 160 | - Parar a execução, condição de sinalização de erro 161 | - Em Python: *raise* uma exceção 162 | raise Exception('string descritiva do erro') 163 | 164 | --------------------------------------- 165 | 166 | ## Testes, Debugging, Assertions 167 | 168 | ### Programação Defensiva 169 | 170 | - Escrever **especificações** para as funções 171 | - **Modularizar** programas 172 | - Checar **condições** em inputs/outputs (*assertions*) 173 | 174 | ### Testando/Validando 175 | 176 | - **Comparar** pares de input/output a uma especificação 177 | - "Não está funcionando!" 178 | - "Como eu posso 'quebrar' o meu programa?" 179 | 180 | ### Debugging 181 | 182 | - **Estudar Eventos** que levam a um erro 183 | - "Por que não está funcionando?" 184 | - "Como eu posso consertar meu programa?" 185 | 186 | --------------------------------------- 187 | 188 | ## Mentalidade para Testing e Debugging 189 | 190 | - Dividir o programa em **módulos** que possam ser testados e debuggados individualmente 191 | - **Documentar especificações** nos módulos 192 | - O que você espera que o input seja? 193 | - O que você espera que o output seja? 194 | - **Documentar suposições** envolvidas no design do código 195 | 196 | --------------------------------------- 197 | 198 | ## Quando você está pronto para testar? 199 | 200 | - Tenha certeza que o código está rodando 201 | - Remova erros de sintaxe 202 | - Remova erros semântico estático 203 | - O interpretador Python normalmente pode encontrar esses erros para você 204 | - Tenha um conjunto de resultados esperados 205 | - Um conjunto de input 206 | - Para cada input, um output esperado 207 | 208 | --------------------------------------- 209 | 210 | ## Classes de Testes 211 | 212 | - Teste Unitário 213 | - Valida cada peça do programa 214 | - Testa cada função separadamente 215 | 216 | - Testa de Regressão 217 | - Adicione testes para bugs conforme você os encontra 218 | - Capture erros reintroduzidos que foram previamente corrigidos 219 | 220 | - Teste de Integração 221 | - O programa completo funciona? 222 | - Normalmente tende-se a vir direto para esta etapa 223 | 224 | --------------------------------------- 225 | 226 | ## Debugging 227 | 228 | - Linha de aprendizado íngrime 229 | - Objetivo é termos um programa livre de bugs 230 | - Ferramentas 231 | - Pré-construída no IDLE e Anaconda 232 | - Python Tutor 233 | - o statement print 234 | 235 | ### Statement Print 236 | 237 | - Uma boa maneira de testar hipóteses 238 | - Quando usar print 239 | - entrada da função 240 | - parâmetros 241 | - resultados de funções 242 | 243 | ### Passos no Debugging 244 | 245 | - Estude o código de programa 246 | - Não pergunte o que está errado 247 | - Pergunte como eu obtive o resultado inesperado 248 | 249 | - Método científico 250 | - Estude dados disponíveis 251 | - Formule hipóteses 252 | - Experimentos repetidos 253 | - Pegue um input simples para testar 254 | 255 | --------------------------------------- 256 | 257 | ## Assertions 258 | 259 | - Tenha certeza que suposições no estado da computação são como o esperado 260 | - Use um statement assert para invocar *raise* de uma exceção *AssertionError* caso as suposições não se concretizem 261 | - Um exemplo de boa **programação defensiva** 262 | 263 | ## Exemplo 264 | 265 | ```python 266 | def media(notas): 267 | # A função encerrará imediatamente caso o assertion não seja concretizado 268 | assert len(notas) != 0, 'nenhum dado para notas' 269 | return sum(notas)/len(notas) 270 | ``` 271 | 272 | - *raises* um *AssertionError* se for dado uma lista vazia para notas 273 | - Caso contrário, roda normal 274 | 275 | Vamos agora criar algumas funções para testarmos 276 | 277 | ```python 278 | def adicao(x, y): 279 | """Função de Adição""" 280 | return x + y 281 | 282 | def subtracao(x, y): 283 | """Função de Subtração""" 284 | return x - y 285 | 286 | def multiplicacao(x, y): 287 | """Função de Multiplicação""" 288 | return x * y 289 | 290 | def divisao(x, y): 291 | """Função de Divisão""" 292 | if y == 0: 293 | raise ValueError("Não é possível dividir por zero") 294 | return x / y 295 | ``` 296 | 297 | Salvamos o arquivo como `operacoes.py` e agora vamos criar nosso arquivo de testes `test_operacoes.py` 298 | 299 | ```python 300 | import unittest 301 | import operacoes 302 | 303 | class TestCalc(unittest.TestCase): 304 | def test_adicao(self): 305 | self.assertEqual(calc.add(10, 5), 15) 306 | self.assertEqual(calc.add(-1, 1), 0) 307 | self.assertEqual(calc.add(-1, -1), -2) 308 | 309 | def test_subtracao(self): 310 | self.assertEqual(calc.subtract(10, 5), 5) 311 | self.assertEqual(calc.subtract(-1, 1), -2) 312 | self.assertEqual(calc.subtract(-1, -1), 0) 313 | 314 | def test_multiplicacao(self): 315 | self.assertEqual(calc.multiply(10, 5), 50) 316 | self.assertEqual(calc.multiply(-1, 1), -1) 317 | self.assertEqual(calc.multiply(-1, -1), 1) 318 | 319 | def test_divisao(self): 320 | self.assertEqual(calc.divide(10, 5), 2) 321 | self.assertEqual(calc.divide(-1, 1), -1) 322 | self.assertEqual(calc.divide(-1, -1), 1) 323 | self.assertEqual(calc.divide(5, 2), 2.5) 324 | 325 | with self.assertRaises(ValueError): # Testando exceções -> ValueError 326 | calc.divide(10, 0) 327 | 328 | if __name__ == '__main__': 329 | unittest.main() 330 | ``` 331 | 332 | Você deve ter observado que tivemos que importar a biblioteca **unittest** em nosso script, ela é muito importante pois permite testar cada função de uma forma que atribuamos os **resultados esperados**, caso os testes venham a falhar, sabemos que há algo de errado com a nossa função. 333 | 334 | Vamos agora executar o teste através do comando `python -m unittest test_operacoes.py` 335 | 336 | O resultado nos traz que os 4 testes foram executados com sucesso 337 | 338 | ``` 339 | Ran 4 tests in 0.001s 340 | 341 | OK 342 | ``` 343 | 344 | Além da biblioteca **unittest** também existem diversas outras, inclusive com funcionalidades mais avançadas, podemos citar por exemplo a biblioteca **pytest**. 345 | 346 | ## Assertions como Programação Defensiva 347 | 348 | - Assertions não permitem o programador controlar a resposta para condições inesperadas 349 | - Tenha certeza que a execução páre quando uma condição esperada não é alcançada 350 | - Tipicamente usado para checar inputs a funções, porém pode ser usado em qualquer lugar 351 | - Pode ser usado para checar outputs de uma função para evitar propagação de valores ruins 352 | - Pode tornar mais fácil a localização da fonte de um bug 353 | 354 | ## Onde usar Assertions? 355 | 356 | - Objetivo é encontrar bugs logo que introduzidos e tornar claro onde eles aconteceram 357 | - Use como um suplemento para testes 358 | - *raise* exceções caso usuários enviem dados de input ruins 359 | - Use assertions para: 360 | - checar tipo de argumentos ou valores 361 | - checar que invariantes em estruturas de dados são encontrados 362 | - checar definições em valores retornados 363 | - checar por violações de definições em um procedimento (exemplo: sem duplicatas em uma lista) 364 | 365 | --------------------------------------- 366 | 367 | Vimos que existem muitos erros e possibilidades deles ocorrerem em nosso programas, por isso é importante que tenhamos em mente a capacidade que **Python** nos traz de lidarmos com estes erros e além disso é essencial que tenhamos em mente a necessidade de testarmos nossos programas para termos sempre a melhor qualidade possível de *software*. Para mais detalhes esteja atento na **[documentação](https://docs.python.org/3/tutorial/errors.html)** 368 | 369 | **Próximo Capítulo**: [Data e Tempo](https://github.com/the-akira/Python-Iluminado/blob/master/Capitulos/21.DataTempo.md) 370 | --------------------------------------------------------------------------------