Fundamentos de Loops e Estruturas de Repetição
Tabela de Multiplicação
Para imprimir a tabela de multiplicação de 1 a 9, utilizamos loops aninhados:
for i in range(1, 10):
for j in range(1, i + 1):
print("{}*{}={}".format(j, i, j * i), end=" ")
print()
Construção de Pirâmides
A construção de pirâmides com asteriscos requer análise matemática. Para uma pirâmide de 5 níveis:
# Fórmula: espaços = nível_máximo - nível_atual
# Fórmula: asteriscos = 2 * nível_atual - 1
nivel = 5
for i in range(1, nivel + 1):
espacos = nivel - i
asteriscos = 2 * i - 1
print(" " * espacos + "*" * asteriscos)
Manipulação de Estruturas de Dados
Fila e Pilha
- Fila (FIFO): append() para adicionar, pop(0) para remover
- Pilha (LIFO): append() para adicionar, pop() para remover
Tuplas e Dicionários
Tuplas são listas imutáveis - a referência de memória não pode mudar, mas podem conter objetos mutáveis como listas:
t = (1, 2, ['A'])
t[2].append('B') # Válido - modifica a lista interna
Para buscar valores em dicionários com segurança:
valor = d.get('chave', None)
Iteradores e Geradores
Iterable vs Iterador
Objetos iteráveis implementam __iter__(), enquanto iteradores implementam tanto __iter__() quanto __next__(). A diferença principal está no estado - iteradores mantêm posição atual:
from collections.abc import Iterable, Iterator
def verificar_tipo(obj):
print(f"{obj} é iterable: {isinstance(obj, Iterable)}")
print(f"{obj} é iterador: {isinstance(obj, Iterator)}")
Geradores
Geradores são iteradores especiais criados com a palavra-chave yield:
def gerador_numeros():
for i in range(5):
yield i
gen = gerador_numeros()
print(next(gen)) # 0
print(next(gen)) # 1
Com yield, a função pausa automaticamente e mantém o estado entre chamadas, ideal para processar grandes volumes de dados sem ocupar memória.
Operações com Arquivos
Copia de Arquivos
def copiar_arquivo(origem, destino):
with open(origem, 'r') as src, open(destino, 'w') as dst:
for linha in src:
dst.write(linha)
Monitoramento de Arquivos (tail -f)
import time
def monitorar_log(arquivo):
with open(arquivo, 'rb') as f:
f.seek(0, 2) # Ir para o final
while True:
linha = f.readline()
if linha:
print(linha.decode('utf-8'), end='')
else:
time.sleep(0.3)
Funções e Escopo de Variáveis
Exercícios com Funções
# Contador usando closure
def criar_contador():
contador = 0
def incremento():
nonlocal contador
contador += 1
return contador
return incremento
contador = criar_contador()
print(contador()) # 1
print(contador()) # 2
Análise de Escopo
Exemplo de resolução de nomes em Python:
x = 111
def func():
print(x) # Busca x no escopo global
func() # Output: 111
x = 111
def func():
print(x) # ReferenceError - variável local não inicializada
x = 222
func()
Decoardores
Decorador Simples
import time
def medidor_tempo(func):
def wrapper(*args, **kwargs):
inicio = time.time()
resultado = func(*args, **kwargs)
print(f"Tempo: {time.time() - inicio}")
return resultado
return wrapper
@medidor_tempo
def processo_lento():
time.sleep(1)
return "Concluído"
Decorador com Autenticação
def autenticar(func):
def wrapper(*args, **kwargs):
if not verificar_login():
return redirect('/login')
return func(*args, **kwargs)
return wrapper
Decorador com Parâmetros
def verificar_permissao(permissao_requerida):
def decorador(func):
def wrapper(*args, **kwargs):
if usuario_tem_permissao(permissao_requerida):
return func(*args, **kwargs)
raise PermissaoNegada()
return wrapper
return decorador
Processamento de Dados com Funções Built-in
Leitura e Processamneto de Arquivos CSV
Dado um arquivo com formato: nome gênero idade salário
egon male 18 3000
alex male 38 30000
wupeiqi female 28 20000
Converter para lista de dicionários:
with open('dados.txt') as arquivo:
linhas = arquivo.readlines()
cabecalhos = ['nome', 'genero', 'idade', 'salario']
pessoas = []
for linha in linhas:
valores = linha.strip().split()
pessoa = dict(zip(cabecalhos, valores))
pessoa['idade'] = int(pessoa['idade'])
pessoa['salario'] = int(pessoa['salario'])
pessoas.append(pessoa)
Funções de Aggregação
# Soma total de salários
total = sum(p['salario'] for p in pessoas)
# Maior salário
maior = max(pessoas, key=lambda p: p['salario'])
# Filtrar homens
ns_homens = [p['nome'] for p in pessoas if p['genero'] == 'male']
# Nomes em maiúsculo
nomes_upper = [p['nome'].upper() for p in pessoas]
# Filtrar nomes que não começam com 'a'
filtrados = [p for p in pessoas if not p['nome'].startswith('a')]
Lambda com max
# Encontrar pessoa mais jovem
mais_jovem = min(pessoas, key=lambda p: p['idade'])
# Encontrar pessoa mais velha
mais_velho = max(pessoas, key=lambda p: p['idade'])
Sistema ATM - Aplicação Completa
Implementar um sistema de ATM com as seguintes operações:
- Registro: Criar nova conta com saldo inicial
- Login: Autenticar usuário com bloqueio após 3 tentativas
- Depósito: Adicionar fundos à conta
- Transferência: Enviar dinheiro entre contas
- Saque: Remover fundos da conta
- Consulta: Verificar saldo atual
Dados armazenados em arquivo texto no formato: usuário:senha:saldo:status
Recursão
Sequência de Fibonacci
def fibonacci(n, a=0, b=1):
if n == 0:
return
print(a, end=' ')
fibonacci(n-1, b, a+b)
fibonacci(10) # 0 1 1 2 3 5 8 13 21 34
Achatamento de Lista Aninhada
def achatar(lista):
resultado = []
for elemento in lista:
if isinstance(elemento, list):
resultado.extend(achatar(elemento))
else:
resultado.append(elemento)
return resultado
numeros = [1, 2, [3, [4, 5, [6, 7]]]]
print(achatar(numeros)) # [1, 2, 3, 4, 5, 6, 7]
Módulos e Importação
Princípios fundamentais:
- Separar código em módulos lógicos
- Compartilhar apenas funções de uso comum
- Nãopoluir o namespace global
Diferença entre executar e importar um módulo:
# Quando executado: __name__ == '__main__'
# Quando importado: __name__ == 'nome_modulo'
if __name__ == '__main__':
main()
O namespace de um módulo importado permanece na memória enquanto o módulo que o importou estiver em execução.