7. Funções#

Uma função é um bloco de código independente que pode ser executado várias vezes em um programa. Ela pode receber entradas (parâmetros), processar dados e retornar uma saída.

A principal característica de uma função é encapsular um conjunto de instruções, facilitando a reutilização e a manutenção do código.

Ao usar funções, o código se torna mais simples e fácil de entender, pois cada função tem um objetivo específico.

Sintaxe Básica#

Para criar uma função, usamos a palavra-chave def, seguida pelo nome da função e, opcionalmente, pelos parâmetros.

A estrutura básica de uma função é a seguinte:

  • def: Palavra-chave que indica a definição de uma função.

  • nome_da_funcao: Nome descritivo que indica o que a função faz.

Exemplo:

def dizer_ola():
    """Esta função apenas imprime uma saudação.""" # Docstring
    print("Olá! Bem-vindo ao mundo das funções.")

# Para usar, você precisa "chamar" a função
dizer_ola()
Olá! Bem-vindo ao mundo das funções.

🔴 Importante: Note o uso de Docstring no inicio da função, ele é utilizado para explicar o que a função faz.

Parâmetros e Argumentos#

Apesar de serem opcionais, parâmetros e argumentos são necessários caso uma função deseje lidar com dados dinâmicos.

  • parâmetro: Valor que a função recebe para processar, sendo a variável listada entre parênteses na definição da função.

  • argumento: É o valor real enviado para a função quando ela é chamada.

Exemplo:

def saudar_usuario(nome): # 'nome' é o parâmetro
    """Esta função apenas imprime uma saudação."""
    print(f"Olá, {nome}! Tudo bem?")

saudar_usuario("Carlos") # "Carlos" é o argumento
Olá, Carlos! Tudo bem?

Parâmetros Padrão (Default)#

Às vezes, queremos que uma função tenha uma opção padrão, para que o usuário não precise preencher tudo todas as vezes. São valores atribuídos aos parâmetros no momento em que a função é definida. Para fazer isso, nós usamos o que chamamos parâmetros padrão.

Eles servem como um valor de reserva, se você chamar a função sem passar esse dado, o sistema utiliza o valor padrão automaticamente, permitindo que a função seja flexível.

Para criar um parâmetro padrão é bem simples, basta usar um operador de atribuição (=) após o nome do parâmetro e em seguida informar o valor padrão que ele terá.

Exemplo:

def criar_email(nome, dominio="gmail.com"): # gmail.com é o valor padrão para o parâmetro dominio
    return f"{nome.lower()}@{dominio}"

# Usando o padrão:
print(criar_email("Carlos")) # carlos@gmail.com

# Alterando o padrão:
print(criar_email("Beatriz", dominio="outlook.com")) # beatriz@outlook.com
carlos@gmail.com
beatriz@outlook.com

⚠️ Atenção: Parâmetros com valor padrão devem sempre vir após os parâmetros obrigatórios. Caso contrário, o Python não saberia quem é quem.

🔴 Importante: Nunca, jamais use objetos mutáveis (listas ou dicionários) como valores padrão. O Python avalia o valor padrão apenas uma vez, na definição da função, e não a cada chamada.

# JEITO ERRADO: Use uma lista como valor padrão.
def adicionar_item(item, lista=[]):
    lista.append(item)
    return lista

print(adicionar_item(1)) # [1]
print(adicionar_item(2)) # [1, 2] - A lista é a mesma da chamada anterior!

print("")

# JEITO Certo: Use None como valor padrão e inicialize a lista dentro da função.
def adicionar_item(item, lista=None):
    if lista is None:
        lista = []
    lista.append(item)
    return lista

print(adicionar_item(1)) # [1]
print(adicionar_item(2)) # [2] - Agora é iniciada uma lista diferente!
[1]
[1, 2]

[1]
[2]

Retorno#

Normalmente, ao executar uma função, desejamos que a função calcule algo e nos devolva este valor para usarmos mais tarde. Para fazermos isto, utilizamos a palavra-chave return juntamente com o valor que desejamos que seja devolvido.

def calcular_area_quadrado(lado):
    """Esta função calcula a área de um quadrado."""
    area = lado * lado
    return area # Devolve o resultado

# Agora posso guardar esse resultado em uma variável
resultado_area = calcular_area_quadrado(5)
print(f"A área é {resultado_area}") # Saída: 25
A área é 25

🔴 Importante: Assim que o Python encontra a palavra return, ele sai da função imediatamente. Qualquer código abaixo do return dentro da função será ignorado.

Escopo Global e Escopo Local#

O escopo determina onde uma variável pode ser acessada dentro do seu programa.

  • Escopo Global: Variáveis criadas fora de qualquer função. Elas são visíveis e podem ser lidas por qualquer parte do código no mesmo arquivo.

  • Escopo Local: Variáveis criadas dentro de uma função. Elas pertencem exclusivamente àquele bloco e deixam de existir assim que a função termina sua execução.

Exemplo:

# Variável no Escopo Global
escola = "Python Academy"

def matricular():
    # Variável no Escopo Local
    aluno = "Lucas"
    print(f"{aluno} foi matriculado na {escola}.")

matricular()
Lucas foi matriculado na Python Academy.

⚠️ ATENÇÃO: Caso print(aluno) estivesse fora do escolpo da função, teríamos causado um NameError, pois ‘aluno’ só existe dentro da função.

Empacotamento de Argumentos (*args e **kwargs)#

O empacotamento permite que uma função receba um número variável de informações sem que você precise definir cada uma delas individualmente.

  • *args (Arguments): Utilizado para capturar múltiplos valores enviados de forma sequencial. O Python agrupa todos esses valores em uma Tupla (uma lista que não pode ser alterada).

  • **kwargs (Keyword Arguments): Utilizado para capturar múltiplos valores enviados com uma “etiqueta” (nome=valor). O Python organiza essas informações em um Dicionário (relação de chave e valor).

Para usarmos ambos é bem simples, apenas precisamos colocar um asterisco (*) entes do nome do parâmetro caso ele seja um *arg e usar dois asterisco caso um **kwargs.

Exemplo:

# Utilizando *args
def calcular_media(*notas):
    # notas é uma tupla: (8, 9, 10, ...)
    if not notas:
        return 0
    return sum(notas) / len(notas)

print(calcular_media(10, 8, 9)) # Passando 3 valores
print(calcular_media(7, 5))     # Passando 2 valores
9.0
6.0
# Utilizando **kwargs
def salvar_usuario(id, **dados):
    # dados é um dicionário: {"nome": "Ana", "idade": 25}
    print(f"Salvando usuário {id}...")
    for chave, valor in dados.items():
        print(f"--- Atributo {chave}: {valor}")

salvar_usuario(101, nome="Ana", idade=25, cidade="São Paulo")
Salvando usuário 101...
--- Atributo nome: Ana
--- Atributo idade: 25
--- Atributo cidade: São Paulo

🎉 Parabéns! Você concluiu o módulo de Funções. Agora você sabe como encapsular lógicas em blocos reutilizáveis, reduzindo a repetição e deixando seus scripts muito mais organizados e fáceis de manter.