Médio Python
Fábrica de multiplicadores com closure
Enunciado
Crie uma função cria_multiplicador(fator) que retorne uma closure. A closure deve receber um número e retornar o produto pelo fator. Use uma closure real (função interna que captura fator).
Requisitos
cria_multiplicadordeve retornar uma função.- A função retornada deve multiplicar seu argumento pelo
fatorcapturado. - Cada chamada a
cria_multiplicadordeve criar uma closure independente.
Código inicial
def cria_multiplicador(fator):
# complete aqui
pass
dobro = cria_multiplicador(2)
triplo = cria_multiplicador(3)
print(dobro(5))
print(triplo(5))
Saída esperada
10
15
Ver dica
Defina uma função dentro de cria_multiplicador que use fator e retorne essa função interna.
Mostrar solução
def cria_multiplicador(fator):
def multiplica(x):
return x * fator # captura 'fator' do escopo externo
return multiplica
dobro = cria_multiplicador(2)
triplo = cria_multiplicador(3)
print(dobro(5)) # 10
print(triplo(5)) # 15
Passo a passo
cria_multiplicador(fator)recebe o fator e o mantém no escopo enclosing (externo à função interna).- Dentro dela, definimos
multiplica(x), que usafatorsem declará-lo como parâmetro. return multiplicadevolve a função interna, não o resultado dela.- Ao chamar
cria_multiplicador(2), o Python cria uma closure que guardafator = 2. dobro(5)executamultiplica(5), que buscafatorno escopo enclosing e calcula5 * 2 = 10.triplo = cria_multiplicador(3)cria outra closure independente comfator = 3.
Por que funciona
A função interna multiplica referencia fator, que não é local nem global. Pela regra LEGB, o Python busca em Enclosing e encontra o parâmetro da função externa. Mesmo após cria_multiplicador retornar, a closure mantém uma referência ao valor de fator, permitindo que multiplica continue funcionando.
Erros comuns
- Retornar o resultado em vez da função:
def cria_multiplicador(fator): def multiplica(x): return x * fator return multiplica(1) # retorna número, não função
`dobro(5)` causaria `TypeError: 'int' object is not callable`.
- Tentar modificar `fator` sem `nonlocal`:
```python
def cria_multiplicador(fator):
def multiplica(x):
fator += 1 # UnboundLocalError
return x * fator
return multiplica
Como fator é atribuído, vira local; use nonlocal fator se precisar alterá-lo.
- Usar variável global em vez de parâmetro, perdendo o encapsulamento.
Outra forma de resolver
Usar functools.partial:
from functools import partial
def multiplica(fator, x):
return x * fator
dobro = partial(multiplica, 2)
print(dobro(5)) # 10
partial é preferível quando você só precisa fixar argumentos, sem lógica adicional na closure.
Saída esperada
10
15