Python oferece um conjunto robusto de funções embutidas que simplificam o desenvolvimento. Entre elas, map, lambda, Pool e random se destacam pela sua utilidade em diversas tarefas de programação.
map()
A função map() é um poderoso recurso de ordem superior que aplica uma função especificada a cada item de um iterável (como uma lista) e retorna um objeto map (que é um iterador). Isso permite processar coleções de dados de forma concisa e eficiente.
class map(object):
"""
map(func, *iterables) --> objeto map
Cria um iterador que computa a função usando argumentos de
cada um dos iteráveis. Para quando o menor iterável é esgotado.
"""
def __getattribute__(self, *args, **kwargs): # assinatura real desconhecida
""" Retorna getattr(self, name). """
pass
def __init__(self, func, *iterables): # assinatura real desconhecida; restaurada de __doc__
pass
def __iter__(self, *args, **kwargs): # assinatura real desconhecida
""" Implementa iter(self). """
pass
@staticmethod # caso conhecido de __new__
def __new__(*args, **kwargs): # assinatura real desconhecida
""" Cria e retorna um novo objeto. Veja help(type) para assinatura precisa. """
pass
def __next__(self, *args, **kwargs): # assinatura real desconhecida
""" Implementa next(self). """
pass
def __reduce__(self, *args, **kwargs): # assinatura real desconhecida
""" Retorna informações de estado para pickling. """
pass
Exemplo prático: Adicionar 1 a cada elemento de uma lista.
numeros = [1, 2, 3, 4, 5]
def adicionar_um(valor):
return valor + 1
resultado_map = map(adicionar_um, numeros)
print(resultado_map) # Imprime o objeto map
for item in resultado_map:
print(item)
# Saída esperada:
# <map object at 0x...>
# 2
# 3
# 4
# 5
# 6
- Expressões
lambda
Expressões lambda, também conhecidas como funções anônimas, permitem a criação de pequenas funções de uma única expressão de forma concisa. A sintaxe é lambda argumentos: expressao, onde a expressão é avaliada e seu resultado é retornado.
multiplicar = lambda x, y: x * y
print(multiplicar(3, 5))
print('-----')
# Combinação com map()
numeros = [1, 2, 3, 4, 5]
for item in map(lambda x: x * 2, numeros):
print(item)
# Saída esperada:
# 15
# -----
# 2
# 4
# 6
# 8
# 10
multiprocessing.Pool
O módulo multiprocessing, e especificamente a classe Pool, é essencial para aprovetiar o poder do paralelismo em CPUs multi-core. Ele permite executar tarefas em processos separados, o que pode ser significativamente mais eficiente do que o multithredaing para tarefas intensivas em CPU.
Um exemplo de execução sequencial de tarefas:
import time
def calcular_quadrado(n):
time.sleep(1) # Simula uma tarefa demorada
return n * n
if __name__ == '__main__':
inicio = time.time()
for p in range(8):
print(calcular_quadrado(p))
print(f"Tempo de execução: {time.time() - inicio:.2f} segundos")
# Saída esperada (aproximada):
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
# Tempo de execução: 8.00 segundos
Execução paralela usando multiprocessing.Pool:
import time
from multiprocessing import Pool
def calcular_quadrado_paralelo(n):
time.sleep(n % 3 + 1) # Simula tempo variável
print(f"Processando {n}")
return n * n
if __name__ == '__main__':
# Cria um pool com 3 processos de trabalho
pool_trabalho = Pool(processes=3)
inicio = time.time()
# Mapeia a função calcular_quadrado_paralelo para os itens em range(8)
# O Pool gerencia a distribuição das tarefas entre os processos disponíveis.
resultados = pool_trabalho.map(calcular_quadrado_paralelo, range(8))
pool_trabalho.close() # Impede que mais tarefas sejam submetidas
pool_trabalho.join() # Aguarda a conclusão de todos os processos filhos
print(resultados)
print(f"Tempo de execução: {time.time() - inicio:.2f} segundos")
# Saída esperada (a ordem das mensagens "Processando" pode variar):
# Processando 0
# Processando 1
# Processando 2
# Processando 3
# Processando 4
# Processando 5
# Processando 6
# Processando 7
# [0, 1, 4, 9, 16, 25, 36, 49]
# Tempo de execução: ~3.xx segundos (depende da distribuição e tempos de sleep)
A classe Pool também fornece mecanismos de sincronização como Lock, Event e Semaphore para gerenciar a comunicação entre processos.
- Módulo
random
O módulo random é fundamental para gerar números pseudoaleatórios, úteis em simulações, jogos, amostragem de dados e muito mais.
import random
# Gera um número de ponto flutuante aleatório entre 0.0 e 1.0
print(f"Aleatório (0-1): {random.random()}")
# Gera um número de ponto flutuante aleatório em um intervalo especificado
print(f"Uniforme (10-20): {random.uniform(10, 20)}")
# Gera um número inteiro aleatório em um intervalo especificado (inclusivo)
print(f"Inteiro (10-20): {random.randint(10, 20)}")
# Gera um número par aleatório em um intervalo especificado (exclusivo no fim)
print(f"Par (0-90): {random.randrange(0, 90, 2)}")
# Seleciona um caractere aleatório de uma string
print(f"Char aleatório: {random.choice('abcdefg')}")
# Seleciona 2 caracteres aleatórios únicos de uma string
print(f"Amostra de chars: {random.sample('abcdefgh', 2)}")
# Seleciona um item aleatório de uma lista
print(f"Item aleatório de lista: {random.choice(['maçã', 'pera', 'laranja'])}")
# Embaralha os itens de uma lista in-place
itens = [1, 2, 3, 4, 5, 6, 7, 8]
random.shuffle(itens)
print(f"Lista embaralhada: {itens}")