Skip to main content

Advanced Functions | Python

  • Advanced Functions | Python

Funções de Ordem Superior | Python

Funções de ordem superior são funções que podem receber outras funções como argumentos e/ou retornar funções como resultado. Elas são uma característica poderosa da programação funcional em Python.

Exemplos de Funções de Ordem Superior

Função map

A função map aplica uma função a todos os itens de um iterável (como uma lista) e retorna um iterador com os resultados.

def quadrado(x):
return x * x

numeros = [1, 2, 3, 4, 5]
resultados = map(quadrado, numeros)
print(list(resultados)) # Saída: [1, 4, 9, 16, 25]

Função filter

A função filter aplica uma função a todos os itens de um iterável e retorna um iterador com os itens para os quais a função retornou True.

def eh_par(x):
return x % 2 == 0

numeros = [1, 2, 3, 4, 5]
pares = filter(eh_par, numeros)
print(list(pares)) # Saída: [2, 4]

Função reduce

A função reduce aplica uma função cumulativa a todos os itens de um iterável, de modo a reduzir o iterável a um único valor. Para usar reduce, é necessário importá-la do módulo functools.

from functools import reduce

def soma(x, y):
return x + y

numeros = [1, 2, 3, 4, 5]
resultado = reduce(soma, numeros)
print(resultado) # Saída: 15

Funções como Retorno

Funções de ordem superior também podem retornar outras funções.

def saudacao(nome):
def mensagem():
return f"Olá, {nome}!"
return mensagem

saudacao_joao = saudacao("João")
print(saudacao_joao()) # Saída: Olá, João!

Funções de ordem superior são uma ferramenta poderosa para escrever código mais modular e reutilizável. Elas permitem que você componha funções de maneira flexível e expressiva.

Closure | Python

Closures são funções que capturam e lembram o ambiente em que foram criadas. Elas podem acessar variáveis locais mesmo após a execução do escopo onde foram definidas. Isso é útil para criar funções com estado ou para encapsular dados.

Exemplo de Closure

def saudacao(nome):
def mensagem():
return f"Olá, {nome}!"
return mensagem

saudacao_joao = saudacao("João")
print(saudacao_joao()) # Saída: Olá, João!

Neste exemplo, a função mensagem é uma closure que captura a variável nome do escopo externo. Mesmo após a execução de saudacao, a função mensagem ainda pode acessar nome.

Outro Exemplo de Closure com Estado

def contador():
count = 0
def incrementar():
nonlocal count
count += 1
return count
return incrementar

contador_incrementar = contador()
print(contador_incrementar()) # Saída: 1
print(contador_incrementar()) # Saída: 2
print(contador_incrementar()) # Saída: 3

Neste exemplo, a função incrementar é uma closure que captura a variável count. A palavra-chave nonlocal é usada para modificar a variável count do escopo externo. A função contador retorna a função incrementar, que mantém o estado de count entre as chamadas.

Closures são uma ferramenta poderosa para criar funções com estado e encapsular dados, tornando o código mais modular e reutilizável.

Iterators | Python

Iterators são objetos que permitem percorrer todos os elementos de uma coleção, como listas ou dicionários, um elemento de cada vez. Em Python, um objeto é considerado um iterador se ele implementa os métodos __iter__() e __next__().

Criando um Iterador

Para criar um iterador, você pode definir uma classe que implementa os métodos __iter__() e __next__(). Aqui está um exemplo simples de um iterador que percorre uma sequência de números:

class Contador:
def __init__(self, limite):
self.limite = limite
self.atual = 0

def __iter__(self):
return self

def __next__(self):
if self.atual < self.limite:
self.atual += 1
return self.atual
else:
raise StopIteration

contador = Contador(5)
for numero in contador:
print(numero) # Saída: 1 2 3 4 5

Usando Iteradores Internos

Python fornece várias funções internas que retornam iteradores, como range, map, filter e zip. Aqui estão alguns exemplos:

Função range

A função range retorna um iterador que gera uma sequência de números.

for i in range(5):
print(i) # Saída: 0 1 2 3 4

Função map

A função map aplica uma função a todos os itens de um iterável e retorna um iterador com os resultados.

def quadrado(x):
return x * x

numeros = [1, 2, 3, 4, 5]
resultados = map(quadrado, numeros)
for resultado in resultados:
print(resultado) # Saída: 1 4 9 16 25

Função filter

A função filter aplica uma função a todos os itens de um iterável e retorna um iterador com os itens para os quais a função retornou True.

def eh_par(x):
return x % 2 == 0

numeros = [1, 2, 3, 4, 5]
pares = filter(eh_par, numeros)
for par in pares:
print(par) # Saída: 2 4

Função zip

A função zip combina vários iteráveis, retornando um iterador de tuplas.

nomes = ["Ana", "Bruno", "Carlos"]
idades = [25, 30, 35]
combinados = zip(nomes, idades)
for nome, idade in combinados:
print(f"{nome} tem {idade} anos") # Saída: Ana tem 25 anos, Bruno tem 30 anos, Carlos tem 35 anos

Iteradores são uma ferramenta poderosa em Python, permitindo que você percorra coleções de maneira eficiente e flexível. Eles são fundamentais para a programação funcional e para a manipulação de grandes conjuntos de dados.

Generators | Python

Generators são uma maneira especial de criar iteradores em Python. Eles permitem que você produza uma sequência de valores ao longo do tempo, em vez de armazenar todos os valores na memória de uma vez. Generators são definidos usando a palavra-chave yield em vez de return.

Criando um Generator

Aqui está um exemplo simples de um generator que produz uma sequência de números:

def contador(limite):
atual = 0
while atual < limite:
atual += 1
yield atual

for numero in contador(5):
print(numero) # Saída: 1 2 3 4 5

Vantagens dos Generators

  1. Eficiência de Memória: Generators produzem itens um de cada vez e só mantêm o estado atual na memória, o que é mais eficiente do que armazenar uma lista completa de valores.
  2. Lazy Evaluation: Os valores são gerados sob demanda, o que pode melhorar o desempenho em casos onde nem todos os valores são necessários.
  3. Simplicidade: Generators são fáceis de implementar e podem substituir iteradores personalizados.

Usando Generators com Funções Internas

Python fornece várias funções internas que retornam generators, como range, map, filter e zip. Aqui estão alguns exemplos:

Função range

A função range retorna um generator que gera uma sequência de números.

for i in range(5):
print(i) # Saída: 0 1 2 3 4

Função map

A função map aplica uma função a todos os itens de um iterável e retorna um generator com os resultados.

def quadrado(x):
return x * x

numeros = [1, 2, 3, 4, 5]
resultados = map(quadrado, numeros)
for resultado in resultados:
print(resultado) # Saída: 1 4 9 16 25

Função filter

A função filter aplica uma função a todos os itens de um iterável e retorna um generator com os itens para os quais a função retornou True.

def eh_par(x):
return x % 2 == 0

numeros = [1, 2, 3, 4, 5]
pares = filter(eh_par, numeros)
for par in pares:
print(par) # Saída: 2 4

Função zip

A função zip combina vários iteráveis, retornando um generator de tuplas.

nomes = ["Ana", "Bruno", "Carlos"]
idades = [25, 30, 35]
combinados = zip(nomes, idades)
for nome, idade in combinados:
print(f"{nome} tem {idade} anos") # Saída: Ana tem 25 anos, Bruno tem 30 anos, Carlos tem 35 anos

Decorators | Python

alt text

Decorators são uma maneira poderosa e elegante de modificar o comportamento de funções ou métodos em Python. Eles permitem que você "envolva" uma função com outra função, adicionando funcionalidade antes e/ou depois da função original ser chamada, sem modificar seu código.

Criando um Decorator

Um decorator é uma função que recebe outra função como argumento e retorna uma nova função que geralmente chama a função original. Aqui está um exemplo simples de um decorator que imprime uma mensagem antes e depois de chamar a função original:

def meu_decorator(func):
def wrapper():
print("Algo está acontecendo antes da função ser chamada.")
func()
print("Algo está acontecendo depois da função ser chamada.")
return wrapper

@meu_decorator
def diz_ola():
print("Olá!")

diz_ola()

Saída:

Algo está acontecendo antes da função ser chamada.
Olá!
Algo está acontecendo depois da função ser chamada.

Decorators com Argumentos

Se a função que você está decorando aceita argumentos, o decorator também deve aceitá-los e passá-los para a função original. Aqui está um exemplo:

def meu_decorator(func):
def wrapper(*args, **kwargs):
print("Algo está acontecendo antes da função ser chamada.")
resultado = func(*args, **kwargs)
print("Algo está acontecendo depois da função ser chamada.")
return resultado
return wrapper

@meu_decorator
def diz_ola(nome):
print(f"Olá, {nome}!")

diz_ola("João")

Saída:

Algo está acontecendo antes da função ser chamada.
Olá, João!
Algo está acontecendo depois da função ser chamada.

Decorators com Argumentos de Decorator

Às vezes, você pode querer passar argumentos para o próprio decorator. Para fazer isso, você precisa criar uma função que retorna o decorator. Aqui está um exemplo:

def repetir_vezes(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator

@repetir_vezes(3)
def diz_ola(nome):
print(f"Olá, {nome}!")

diz_ola("João")

Saída:

Olá, João!
Olá, João!
Olá, João!

Decorators para Métodos de Classe

Decorators também podem ser usados para métodos de classe. Aqui está um exemplo de um decorator que verifica se um usuário está autenticado antes de permitir a execução de um método:

def requer_autenticacao(func):
def wrapper(self, *args, **kwargs):
if not self.autenticado:
print("Usuário não autenticado!")
return
return func(self, *args, **kwargs)
return wrapper

class Usuario:
def __init__(self, nome):
self.nome = nome
self.autenticado = False

@requer_autenticacao
def acessar_sistema(self):
print(f"{self.nome} acessou o sistema.")

usuario = Usuario("João")
usuario.acessar_sistema() # Saída: Usuário não autenticado!
usuario.autenticado = True
usuario.acessar_sistema() # Saída: João acessou o sistema.

Decorators são uma ferramenta poderosa para adicionar funcionalidades de maneira modular e reutilizável. Eles são amplamente utilizados em frameworks web, como Flask e Django, para adicionar funcionalidades como autenticação, logging e caching.