Aprofundamento em programação com Python
Conteúdos
- Controle de Fluxo
- Estruturas de repetição
- Funções
- Orientação a Objetos
- Instalação de bibliotecas
- Importação de bibliotecas
Controle de fluxo
Nem sempre nosso código deve se comportar de maneira igual para todas as situações, às vezes precisamos tomar uma decisão em função de nossas operações em situações específicas e para isso podemos utilizar estruturas de condição.
if
Quando falamos em tomar decisões, a estrutura que trabalhamos é sempre o if
, que é uma estrutura que testa condições impostas para decidir como prosseguir em certas situações, como por exemplo checar se um número é maior, menor ou igual a outro. Testando uma condição única:
if 10 < 30:
print('10 é menor que 30')
Podemos também testar múltiplas condições exigindo que todas sejam verdadeiras ou apenas uma seja, dependendo do operador usado: or ou and. Precisamos separar essas diferentes condições usando parentêsis.
O operador or
, “ou” traduzindo do inglês, faz com que a condição seja satisfeita se a primeira ou a segunda expressão (ou as duas) forem verdadeiras. Pode ser também representado pelo caractere |
if (7 < 3) or (5 > 1):
print('Pelo menos um é verdade')
Já o operador and
, “e” traduzindo do inglês, faz com que a condição seja satisfeita se a primeira e a segunda expressão sejam verdadeiras Pode ser também representado pelo caractere &
if (7 == 7) and (5 > 1):
print('Ambas expressões são verdadeiras')
else
Para toda situação sempre podemos incluir uma saída padrão como resposta se a condição não for satisfeita, para isso temos o else
.
= 40
n if n < 30:
print('%i é menor que 30'%(n))
else:
print('%i é maior ou igual a 30'%(n))
elif
Podemos também incluir mais de uma condição a ser testada, adicionando mais instâncias do if ao mesmo if com a estrutura elif
.
= 40
n if n < 30:
print('%i é menor que 30'%(n))
elif n > 30:
print('%i é maior que 30'%(n))
else:
print('%i é igual a 30'%(n))
Estruturas de repetição
No python, assim como qualquer linguagem de programação, existe o que chamamos de estruturas de repetição. Elas servem para executar um mesmo comando mais de uma vez, muito útil quando trabalhando com listas.
for
O for
é uma estrutura de repetição que percorre um escopo de valores específicos, por exemplo se queremos printar os números de 0 até 10 podemos escrever desta forma:
for numero in range(0,10):
print(numero)
Note que o primeiro número impresso é o 0 como especificado e o último número o 9. A variável numero armazena o valor de cada iteração do loop, mas o for sempre para antes do último número, que seria o 10, porque o Python é uma linguagem que começa com 0 invés de 1, e descartar esse último número auxilia na hora de iterar listas, a principal razão do uso do laço for. Observe como percorrer os elementos de uma lista:
= ['jan', 'fev', 'mar', 'abr', 'mai', 'jun']
meses for i in range(length(meses)):
print(meses[i])
Por convenção, no python usamos como variável do loop o i
se quisermos percorrer uma lista. Usar um for dentro de outro serve para percorrer uma matriz. Nesse caso usaremos j
no segundo. Se mais uma dimensão for adicionada será k
. Para ordens ainda maiores não existe uma convenção, porém, eu utilizo o alfabeto invés de i, j, k.
= [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matriz for i in range(length(matriz)):
for j in range(length(matriz[i])):
print(matriz[i][j])
Existe uma alternativa ao range de como percorrer uma lista com o for. O range cria esses índices para serem referenciados na lista. Podemos salvar os elementos direto na variável do loop como feito a seguir:
= ['jan', 'fev', 'mar', 'abr', 'mai', 'jun']
meses for mes in meses:
print(mes)
O problema de usar o loop dessa forma é que não podemos alterar a lista original já que perdemos a referência numérica dela. Existem situações que o primeiro método é preferível e situações que o segundo método é preferível.
while
O while
é um loop que enquanto uma condição não for satisfeita ou enquanto ela for satisfeita esse loop permanecerá ocorrendo, usado principalmente quando o número de iterações do loop não é definido por um número e sim por uma condição.
= ['cachorro', 'gato', 'rato', 'macaco', 'cachorro', 'cachorro', 'elefante', 'leao']
animais while 'cachorro' in animais:
'cachorro')
animais.remove(print(animais)
Repare que 'cachorro'
foi removido mais de uma vez da lista de animais. Uma vez que não haviam mais cachorros na lista de animais, o loop do while foi finalizado.
break e flags
Podemos interromper o while utilizando o break
ou flags, como nos exemplos abaixo:
# Saudando pessoas até que elas queiram sair do programa com o break
while True:
= input('Digite seu nome para que eu possa te dar um oi!:\n'+'(Entre com "quit" para sair da aplicacao)\n\n')
resposta
if resposta.lower() == 'quit':
break
# SE CAIR NA CONDIÇÃO DO `BREAK` AS LINHAS ABAIXO DESTE COMENTÁRIO NÃO SERÃO EXECUTADAS!!!
print('Olá, ' + resposta)
Um exemplo com flags que são variáveis booleanas que controlam o fluxo.
= True
continuar_execucao while continuar_execucao:
= input('Digite seu nome para que eu possa te dar um oi!:\n'+'(Entre com "quit" para sair da aplicacao)\n\n')
resposta if resposta.lower() != 'quit':
print('Olá, ' + resposta)
else:
= False continuar_execucao
continue
Também podemos dar continuidade a um ciclo com a utilização do continue
.
while True:
= input('Digite seu nome para que eu possa te dar um oi!:\n' + '(Entre com "quit" para sair da aplicacao)\n\n')
resposta if resposta == '':
print('Digite um nome válido!')
continue
# SE O USUÁRIO APENAS PRECIONAR ENTER SEM ADICIONAR SEU NOME O CICLO REINICIARÁ E PEDIRA NOVAMENTE PARA QUE
# DIGITE SEU NOME.
if resposta.lower() == 'quit':
break
# SE CAIR NA CONDIÇÃO DO `BREAK` AS LINHAS ABAIXO DESTE COMENTÁRIO NÃO SERÃO EXECUTADAS!!!
print('Olá, ' + resposta)
Repare que o print('Olá, ' + resposta)
não foi feito porque na primeira iteração o loop caiu no continue e no segundo no break porque o quit foi digitado.
Funções
Várias vezes na programação repetimos a mesma tarefa várias vezes ou precisamos criar uma tarefa que possa ser usada mais tarde em outro programa, para evitar repetição de código e seguir um dos princípios da programação que é a modulação utilizamos da criação de funções.
Em resumo, funções são um escopo de código que pode ser chamado para realizar uma tarefa específica, podem ter ou não um tipo de retorno, possuem um título e podem ter ou não parâmetros passados para a função.
Em python utilizamos a sintaxe: def nome_da_funcao(parametros): #escopo da função return objeto_a_ser_retornado
Os exemplos mais simples de funções podem ser vistos abaixo:
def soma(a, b): #definição/criação da função
return a + b #escopo da função
3, 4) #chamada da função soma(
def ola_mundo():
print('Olá, Mundo!')
ola_mundo()
Exemplo de uma função com retorno de um objeto do tipo lista:
def formata_nomes(nomes):
= []
lista_formatada for nome in nomes:
lista_formatada.append(nome.title()) return lista_formatada
= ['dAnIeL', 'iGoR', 'caRoLINA']
lista_nao_formatada = formata_nomes(lista_formatada)
lista_formatada print(lista_formatada)
Orientação a objetos
No mundo da programação existem diversas linguagens. As linguagens são criadas seguindo paradigmas por vezes distintos, isso é, diferentes lingugagens seguem diferentes formas de se encarar o próprio ato de programar, podendo ainda seguir mais de um paradigma diferente. No python, um dos paradigmas explorados é o de orientação a objetos.
Uma linguagem orientada a objetos escreve seus programas baseados em classes e objetos. Para entender o que são classes e objetos precisamos fazer um paralelo com o mundo real, por exemplo um carro.
Um carro possui características específicas: modelo, cor, velocidade. O carro possui ainda comportamentos: acelerar e freiar, acessíveis pelo motorista para usar quando quiser. Na programação, o carro é o objeto, a ideia do que é um carro é a classe e o motorista é o programador que usa o carro em seu programa.
Traduzindo para python:
class Carro():
def __init__(self, modelo, cor, velocidade):
self.modelo = modelo
self.cor = cor
self.velocidade = velocidade
def getModelo(self):
return self.modelo
def getCor(self):
return self.cor
def getVelocidade(self):
return self.velocidade
def acelerar(self, incrementoVelocidade):
self.velocidade = self.velocidade + incrementoVelocidade
def freiar(self, decrementoVelocidade):
if self.velocidade < decrementoVelocidade:
self.velocidade = 0
else:
self.velocidade = self.velocidade - decrementoVelocidade
= Carro("Gol", "vermelho", 0) meuCarro
O comando class do python funciona semelhante ao def, porém define uma classe. Dentro da definição da classe, diversas “funções” foram definidas: __init__, getModelo, getCor, getVelocidade, acelerar, freiar. O nome de funções no contexto de um objeto é método. Métodos são semelhantes a funções, porém utilizam também como variáveis os atributos da classe, isso é, são os comportamentos do carro e usam as características do carro. Na definição, os métodos da classe têm os argumentos começando com o self se forem usar algum atributo do objeto, na hora de utilizar esses metodos, não se escreve o self, uma vez que o metodo que parte do objeto em questão já entende que o mesmo é o “self”.
O método __init__ é um método especial, ele pode ser chamado de construtor. Ele receberá como argumentos as características que julgamos necessárias para definir nosso objeto. Na linha meuCarro = Carro(“Gol”, “vermelho”, 0), o método __init__ é chamado e retorna um objeto da classe Carro de modelo “Gol”, de cor “vermelha” e velocidade 0. Sempre com o nome da classe e os argumentos do método __init__ da classe em questão (exceto o self), essa função constroi o objeto.
Para usar os métodos precisa digitar a variável em que o objeto está armazenado depois .nomeDoMetodo(argumentos) como segue no exemplo abaixo:
print("Velocidade antes de acelerar:", meuCarro.getVelocidade())
10)
meuCarro.acelerar(print("Velocidade depois de acelerar:", meuCarro.getVelocidade())
O código do exemplo mudou a velocidade do objeto meuCarro, que originalmente era 0 e passou para 10.
Para acessar os atributos (características) do objeto, normalmente se usa esses métodos do tipo getAtributo(). Pode-se, também, trazendo pro contexto do exemplo, acessar usando apenas meuCarro.velocidade invés de meuCarro.getVelocidade(). Semelhante a como é feito a chamada dos métodos, porém sem o () no final. Embora possa parecer mais simples acessar a velocidade diretamente, sem criar e chamar o método getVelocidade, em orientação a objetos existem algumas práticas que todo o programador deve seguir, essa é uma delas, o encapsulamento, que consiste em esconder os detalhes da implementação da classe do objeto criado.
Essa regra do encapsulamento e outras regrinhas não são importantes de se saber para o contexto de ciência de dados. Orientação a objetos é toda uma forma de se programar, um assunto extenso, imprescindível no processo de criação de um software, não necessariamente para se usar um. É importante saber o básico para entender o que está acontecendo por baixo de bibliotecas, que comumente utilizam classes. O matplotlib, uma biblioteca de visualização de dados, por exemplo, tem um objeto de uma classe de visualizações como meio de se criar as imagens de visualização de dados, todos os comandos de como criar os gráficos são feitos por métodos desse objeto.
Instalação de bibliotecas
O píp
é um repositório que guarda uma quantidade enorme de pacotes e módulos para utilizarmos em nossas aplicações. Se o Python estiver adicionado ao PATH digite no terminal do windows:
~~~ $ pip –version ~~~
Caso seu pip esteja desatualizado utilize:
$ python -m pip install --upgrade pip
Para instalar algum pacote execute:
$ pip install "nome do pacote"
ou ainda
$ python -m pip install "nome do pacote"
Importação
Agora veremos as diferentes formas de importar módulos (os pacotes do python) para seu ambiente.
import numpy # Importa o módulo numpy
import pandas as pd # Importa o módulo pandas com um alias pd
import matplotlib.pyplot as plt # Importa a classe pyplot dentro do pacote matplotlib com o alias plt
from os import getcwd # Importa apenas a função getcwd do módulo os
from time import asctime as data # Importa a penas a função asctime com o alias data
from statistics import * # Importa tudo que pertence ao módulo statistics
Alias é o “apelido” que o módulo terá no código, ou seja, apenas precisamos chamar o alias para referenciar o módulo
Vejamos agora como cada forma de importação é utilizada!
Veja que o numpy foi importado utilizando import numpy
dessa forma devemos sempre colocar o nome do módulo antes de utilizar os métodos e atributos que ele possui
60)
numpy.random.seed(0, 1, 10) # Cria um array aleatório de tamanho 10 com distriuição normal mu = 0, sigma = 1. numpy.random.normal(
Já em from os import getcwd
apenas importamos a função getcwd
do módulo os
# Retorna o diretório atual do workspace. getcwd()
Utilizando o comando from time import asctime as data
importamos a função asctime do módulo time e adicionamos um alias data utilizando a keyword as
.
# Retorna a data de hoje data()
Ao utilizar from statistics import *
estamos importando todas as funções e métodos pertencentes ao módulo statistics. Não é aconselhável utilizar já que o código perde semântica.
35)
numpy.random.seed(= numpy.random.randint(1, 20, 30)
numbers
print(mean(numbers))
print(harmonic_mean(numbers))
print(median(numbers))
Referências
MATTHES, Eric. Python Crash Course: A Hands-On, Project-Based Introduction to Programming. San Francisco: No Starch Press, 2016.
LUTZ, Mark. Learning Python. Estados Unidos: O’Reilly Media, 2013.