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_multiplicador deve retornar uma função.
  • A função retornada deve multiplicar seu argumento pelo fator capturado.
  • Cada chamada a cria_multiplicador deve 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

  1. cria_multiplicador(fator) recebe o fator e o mantém no escopo enclosing (externo à função interna).
  2. Dentro dela, definimos multiplica(x), que usa fator sem declará-lo como parâmetro.
  3. return multiplica devolve a função interna, não o resultado dela.
  4. Ao chamar cria_multiplicador(2), o Python cria uma closure que guarda fator = 2.
  5. dobro(5) executa multiplica(5), que busca fator no escopo enclosing e calcula 5 * 2 = 10.
  6. triplo = cria_multiplicador(3) cria outra closure independente com fator = 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