Funcao: O que É e Como Funciona | Python Brasil
Aprenda tudo sobre funcoes em Python: definicao, parametros, retorno, escopo, closures, decoradores e boas praticas para organizar seu codigo.
O que e uma Funcao?
Uma funcao em Python e um bloco de codigo reutilizavel que executa uma tarefa especifica. Funcoes sao a principal ferramenta de abstracao e organizacao da linguagem, permitindo dividir programas complexos em partes menores, mais legiveis e mais faceis de manter. Em Python, funcoes sao definidas com a palavra-chave def e sao objetos de primeira classe, o que significa que podem ser atribuidas a variaveis, passadas como argumentos e retornadas por outras funcoes.
Como Definir Funcoes
# Funcao simples
def saudacao():
print('Ola, mundo!')
saudacao() # Ola, mundo!
# Funcao com parametros e retorno
def somar(a, b):
return a + b
resultado = somar(3, 5)
print(resultado) # 8
# Funcao com docstring
def calcular_area(base, altura):
"""Calcula a area de um triangulo.
Args:
base (float): A base do triangulo.
altura (float): A altura do triangulo.
Returns:
float: A area calculada.
"""
return (base * altura) / 2
Tipos de Parametros
Python oferece grande flexibilidade na definicao de parametros de funcoes.
# Parametros posicionais e com valor padrao
def criar_usuario(nome, email, ativo=True):
return {'nome': nome, 'email': email, 'ativo': ativo}
usuario = criar_usuario('Ana', 'ana@email.com')
usuario2 = criar_usuario('Bruno', 'bruno@email.com', ativo=False)
# *args — numero variavel de argumentos posicionais
def calcular_media(*notas):
if not notas:
return 0
return sum(notas) / len(notas)
print(calcular_media(7.5, 8.0, 9.0)) # 8.166...
print(calcular_media(10, 9)) # 9.5
# **kwargs — numero variavel de argumentos nomeados
def criar_perfil(nome, **detalhes):
perfil = {'nome': nome}
perfil.update(detalhes)
return perfil
perfil = criar_perfil('Ana', cidade='Sao Paulo', idade=28)
print(perfil) # {'nome': 'Ana', 'cidade': 'Sao Paulo', 'idade': 28}
# Parametros somente posicionais (/) e somente nomeados (*)
def dividir(a, b, /, *, arredondar=False):
resultado = a / b
if arredondar:
return round(resultado, 2)
return resultado
print(dividir(10, 3, arredondar=True)) # 3.33
Retorno de Valores
# Retorno simples
def quadrado(n):
return n ** 2
# Retorno multiplo (na verdade retorna uma tupla)
def dividir_com_resto(a, b):
quociente = a // b
resto = a % b
return quociente, resto
q, r = dividir_com_resto(17, 5)
print(f'Quociente: {q}, Resto: {r}') # Quociente: 3, Resto: 2
# Funcao sem return explicito retorna None
def apenas_imprime(msg):
print(msg)
resultado = apenas_imprime('oi')
print(resultado) # None
Escopo de Variaveis
O escopo determina onde uma variavel e acessivel. Python segue a regra LEGB: Local, Enclosing, Global, Built-in.
x = 'global'
def funcao_externa():
x = 'enclosing'
def funcao_interna():
x = 'local'
print(x) # 'local'
funcao_interna()
print(x) # 'enclosing'
funcao_externa()
print(x) # 'global'
# Usando global e nonlocal
contador = 0
def incrementar():
global contador
contador += 1
def funcao_externa2():
valor = 10
def funcao_interna2():
nonlocal valor
valor += 5
funcao_interna2()
print(valor) # 15
Funcoes como Objetos de Primeira Classe
# Atribuir funcao a variavel
def gritar(texto):
return texto.upper()
funcao = gritar
print(funcao('ola')) # 'OLA'
# Passar funcao como argumento
def aplicar(funcao, valor):
return funcao(valor)
print(aplicar(abs, -42)) # 42
print(aplicar(str.upper, 'a')) # 'A'
# Retornar funcao de outra funcao
def multiplicador(fator):
def multiplicar(numero):
return numero * fator
return multiplicar
dobro = multiplicador(2)
triplo = multiplicador(3)
print(dobro(5)) # 10
print(triplo(5)) # 15
Closures
Uma closure e uma funcao interna que “lembra” das variaveis do escopo onde foi definida, mesmo apos a funcao externa ter terminado.
def criar_contador(inicio=0):
contagem = [inicio] # lista para contornar a imutabilidade
def contar():
contagem[0] += 1
return contagem[0]
return contar
contador = criar_contador()
print(contador()) # 1
print(contador()) # 2
print(contador()) # 3
Type Hints em Funcoes
def buscar_usuario(user_id: int) -> dict | None:
"""Busca um usuario pelo ID."""
usuarios = {1: {'nome': 'Ana'}, 2: {'nome': 'Bruno'}}
return usuarios.get(user_id)
def processar_itens(itens: list[str], limite: int = 10) -> list[str]:
"""Processa e retorna no maximo 'limite' itens."""
return [item.strip().lower() for item in itens[:limite]]
Erros Comuns
O erro mais frequente e usar objetos mutaveis como valores padrao de parametros, como def func(lista=[]). O Python avalia o valor padrao apenas uma vez, fazendo com que chamadas diferentes compartilhem o mesmo objeto. O correto e usar None e criar o objeto dentro da funcao. Outro erro comum e esquecer os parenteses ao chamar uma funcao, resultando em uma referencia ao objeto funcao em vez de sua execucao. Tambem e comum confundir return com print — funcoes que apenas imprimem valores nao permitem que o resultado seja usado em outras partes do codigo.
Boas Praticas
Cada funcao deve ter uma unica responsabilidade, seguindo o principio de responsabilidade unica. Nomes de funcoes devem ser descritivos e usar snake_case. Inclua docstrings que expliquem o proposito, parametros e retorno. Use type hints para documentar os tipos esperados. Mantenha funcoes curtas — se uma funcao tem mais de 20-30 linhas, considere dividi-la. Evite efeitos colaterais inesperados e prefira funcoes puras sempre que possivel.
Quando Usar
Funcoes devem ser usadas sempre que um trecho de codigo se repete ou quando voce quer isolar uma logica especifica. Elas sao a base para construir programas modulares, testaveis e faceis de manter. Mesmo trechos de codigo executados apenas uma vez podem se beneficiar de estar em uma funcao, pois o nome da funcao documenta a intencao do codigo.