19. Definindo e Chamando Funções
19.1) O Que São Funções e Por Que Elas Importam
Uma função(function) é um bloco nomeado de código que realiza uma tarefa específica. Você já vem usando funções ao longo deste livro — print(), input(), len(), type(), e muitas outras. Essas são funções embutidas (built-in functions) que o Python fornece. Agora você vai aprender a criar suas próprias funções personalizadas (custom functions) para organizar seu código e torná-lo reutilizável.
Por Que Funções Importam
Funções são fundamentais para escrever programas claros e fáceis de manter. Elas oferecem vários benefícios críticos:
1. Reutilização de Código
Sem funções, você precisaria copiar e colar o mesmo código toda vez que quisesse realizar uma tarefa. Considere calcular a área de um retângulo em vários lugares:
# Sem funções - código repetitivo
length1 = 5
width1 = 3
area1 = length1 * width1
print(f"Area 1: {area1}")
length2 = 8
width2 = 4
area2 = length2 * width2
print(f"Area 2: {area2}")
length3 = 10
width3 = 6
area3 = length3 * width3
print(f"Area 3: {area3}")Output:
Area 1: 15
Area 2: 32
Area 3: 60Essa repetição é cansativa e propensa a erros. Se você precisar mudar como calcula a área (talvez para incluir unidades ou arredondamento), teria que atualizar cada lugar. Funções resolvem esse problema permitindo que você escreva o código uma vez e o use muitas vezes.
2. Organização de Código
Funções quebram programas grandes em partes menores e gerenciáveis. Cada função lida com uma tarefa específica, deixando seu código mais fácil de entender e manter. Em vez de um script longo com centenas de linhas, você pode organizar operações relacionadas em funções nomeadas que comunicam claramente seu propósito.
3. Abstração (abstraction)
Funções escondem detalhes de implementação por trás de uma interface simples. Quando você chama len(my_list), você não precisa saber como o Python conta os elementos — você só obtém o resultado. Da mesma forma, suas funções podem oferecer interfaces simples para operações complexas, deixando seu código mais fácil de usar e entender.
4. Testes e Depuração (debugging)
Funções facilitam testar partes individuais do seu programa. Você pode verificar se cada função funciona corretamente de forma isolada antes de combiná-las em um programa maior. Quando algo dá errado, funções ajudam você a reduzir onde o problema está acontecendo.
Ao longo do restante deste capítulo, você vai aprender como definir suas próprias funções, passar informações para elas, obter resultados de volta e documentá-las de forma clara. Essas habilidades são essenciais para escrever código Python profissional.
19.2) Definindo Funções com def
Para criar uma função em Python, você usa a palavra-chave def (abreviação de "define"). A estrutura básica de uma definição de função parece com isto:
def function_name():
# Bloco de código que roda quando a função é chamada
statement1
statement2
# ... mais instruçõesVamos detalhar cada parte:
def: A palavra-chave que diz ao Python que você está definindo uma funçãofunction_name: O nome que você escolhe para sua função (segue as mesmas regras dos nomes de variáveis)(): Parênteses que vão eventualmente conter parâmetros (vamos cobrir isso na próxima seção):: Dois-pontos que marcam o fim do cabeçalho da função- Bloco de código indentado: As instruções que compõem o corpo da função (devem estar indentadas)
Sua Primeira Função
Aqui está uma função simples que imprime uma saudação:
def greet():
print("Hello!")
print("Welcome to Python functions.")
# Chame a função
greet()Output:
Hello!
Welcome to Python functions.Quando você define uma função, o Python lembra dela, mas não executa o código dentro imediatamente. O código só roda quando você chama (call) a função escrevendo seu nome seguido de parênteses: greet().
Convenções de Nomeação de Funções
Nomes de funções seguem as mesmas regras dos nomes de variáveis (como aprendemos no Capítulo 3):
- Use letras minúsculas
- Separe palavras com underscores (snake_case)
- Comece com uma letra ou underscore, não com um dígito
- Use nomes descritivos que indiquem o que a função faz
# Bons nomes de funções
def calculate_total():
pass
def get_user_age():
pass
def display_menu():
pass
# Nomes ruins de funções (mas sintaticamente válidos)
def x(): # Não é descritivo
pass
def CalculateTotal(): # Deve usar minúsculas
pass
def calc(): # Abreviação demais
passNota: Usamos pass aqui como um placeholder (como aprendemos no Capítulo 8). Ele não faz nada, mas permite que a definição da função fique sintaticamente completa.
Funções Podem Conter Qualquer Código
O corpo de uma função pode conter qualquer instrução Python que você tenha aprendido até agora: atribuições de variáveis, condicionais, loops, e até chamadas para outras funções.
def check_temperature():
temperature = 72
if temperature > 75:
print("It's warm.")
elif temperature > 60:
print("It's comfortable.")
else:
print("It's cool.")
check_temperature()Output:
It's comfortable.Múltiplas Definições de Função
Você pode definir quantas funções precisar no seu programa. Cada função é independente e pode ser chamada separadamente:
def morning_greeting():
print("Good morning!")
def evening_greeting():
print("Good evening!")
# Chame cada função
morning_greeting()
evening_greeting()Output:
Good morning!
Good evening!Ordem de Definição de Funções
Em Python, você deve definir uma função antes de chamá-la. O interpretador Python lê seu código de cima para baixo, então se você tentar chamar uma função antes de defini-la, você vai receber um erro:
# WARNING: This will cause a NameError - for demonstration only
# PROBLEM: Function called before it's defined
say_hello() # NameError: name 'say_hello' is not defined
def say_hello():
print("Hello!")A ordem correta é definir primeiro e depois chamar:
# Correto: defina primeiro
def say_hello():
print("Hello!")
# Depois chame
say_hello()Output:
Hello!No entanto, funções podem chamar outras funções que são definidas mais tarde no arquivo, desde que essas chamadas aconteçam depois de todas as definições:
def first_function():
print("First function")
second_function() # Isso está ok - chamada em runtime
def second_function():
print("Second function")
# Ambas as funções estão definidas antes de chamarmos a primeira
first_function()Output:
First function
Second functionFunções Criam Escopo Local (local scope)
Variáveis criadas dentro de uma função existem apenas dentro dessa função. Isso é chamado de escopo local (local scope) (vamos explorar isso em detalhes no Capítulo 21). Por enquanto, entenda que o que acontece dentro de uma função fica dentro da função:
def create_message():
message = "This is local"
print(message)
create_message()
# Isso causaria um erro:
# print(message) # NameError: name 'message' is not definedOutput:
This is localA variável message existe apenas enquanto a função está rodando. Quando a função termina, a variável desaparece.
Funções Vazias com pass
Às vezes você quer definir a estrutura de uma função, mas implementá-la depois. Use pass como placeholder:
def future_feature():
pass # TODO: Implemente isso depois
# A função existe e pode ser chamada, mas não faz nada
future_feature() # Roda sem erro, não faz nadaIsso é útil quando você está esboçando a estrutura do seu programa antes de preencher os detalhes.
19.3) Chamando Funções e Passando Argumentos
Definir uma função cria um pedaço reutilizável de código, mas para deixar funções realmente poderosas, você precisa passar informações para elas. Essas informações são passadas por meio de argumentos (arguments).
Parâmetros vs Argumentos
Antes de continuar, vamos esclarecer dois termos que muitas vezes são confundidos:
- Parâmetro (parameter): Um nome de variável na definição da função que vai receber um valor
- Argumento (argument): O valor real que você passa para a função quando a chama
def greet(name): # 'name' é um parâmetro
print(f"Hello, {name}!")
greet("Alice") # "Alice" é um argumentoOutput:
Hello, Alice!Pense em parâmetros como placeholders e argumentos como os dados reais que preenchem esses placeholders.
Definindo Funções com Parâmetros
Para definir uma função que aceita entrada, adicione nomes de parâmetros dentro dos parênteses:
def greet_person(name):
print(f"Hello, {name}!")
print("Nice to meet you.")
# Chame com argumentos diferentes
greet_person("Alice")
print() # Linha em branco para legibilidade
greet_person("Bob")Output:
Hello, Alice!
Nice to meet you.
Hello, Bob!
Nice to meet you.O parâmetro name atua como uma variável dentro da função. Cada vez que você chama a função, name assume o valor do argumento que você fornece.
Múltiplos Parâmetros
Funções podem aceitar múltiplos parâmetros, separados por vírgulas:
def calculate_rectangle_area(length, width):
area = length * width
print(f"A rectangle with length {length} and width {width}")
print(f"has an area of {area} square units.")
calculate_rectangle_area(5, 3)
print()
calculate_rectangle_area(10, 7)Output:
A rectangle with length 5 and width 3
has an area of 15 square units.
A rectangle with length 10 and width 7
has an area of 70 square units.Ao chamar uma função com múltiplos parâmetros, a ordem importa. O primeiro argumento vai para o primeiro parâmetro, o segundo argumento para o segundo parâmetro, e assim por diante. Esses são chamados de argumentos posicionais (positional arguments).
Argumentos Posicionais
Com argumentos posicionais, o Python associa argumentos a parâmetros com base na posição:
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
describe_pet("dog", "Buddy")
print()
describe_pet("cat", "Whiskers")Output:
I have a dog.
My dog's name is Buddy.
I have a cat.
My cat's name is Whiskers.Se você trocar a ordem, vai ter resultados inesperados:
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
# Argumentos na ordem errada
describe_pet("Buddy", "dog")Output:
I have a Buddy.
My Buddy's name is dog.Isso é tecnicamente Python válido, mas produz uma saída sem sentido porque os argumentos estão nas posições erradas.
Argumentos Nomeados (keyword arguments)
Para evitar erros relacionados à posição, você pode usar argumentos nomeados (keyword arguments) nomeando explicitamente os parâmetros ao chamar a função:
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name}.")
# Usando argumentos nomeados - a ordem não importa
describe_pet(animal_type="dog", pet_name="Buddy")
print()
describe_pet(pet_name="Whiskers", animal_type="cat")Output:
I have a dog.
My dog's name is Buddy.
I have a cat.
My cat's name is Whiskers.Com argumentos nomeados, a ordem não importa porque o Python associa argumentos a parâmetros pelo nome, não pela posição.
Misturando Argumentos Posicionais e Nomeados
Você pode misturar argumentos posicionais e nomeados em uma única chamada de função, mas argumentos posicionais devem vir primeiro:
def create_profile(username, email, age):
print(f"Username: {username}")
print(f"Email: {email}")
print(f"Age: {age}")
# Misturando argumentos posicionais e nomeados
create_profile("alice123", email="alice@example.com", age=25)Output:
Username: alice123
Email: alice@example.com
Age: 25No entanto, você não pode colocar argumentos posicionais depois de argumentos nomeados:
# WARNING: This will cause a SyntaxError - for demonstration only
# PROBLEM: Positional argument after keyword argument
# create_profile(username="alice123", "alice@example.com", 25)
# SyntaxError: positional argument follows keyword argumentA Quantidade de Argumentos Deve Bater
Quando você chama uma função, você deve fornecer o número correto de argumentos (a menos que a função tenha valores padrão, o que veremos no Capítulo 20):
def add_numbers(a, b):
result = a + b
print(f"{a} + {b} = {result}")
add_numbers(5, 3) # Correto: 2 argumentos para 2 parâmetrosOutput:
5 + 3 = 8Fornecer argumentos de menos ou demais causa um erro:
# WARNING: These will cause TypeErrors - for demonstration only
# PROBLEM: Too few arguments
# add_numbers(5)
# TypeError: add_numbers() missing 1 required positional argument: 'b'
# PROBLEM: Too many arguments
# add_numbers(5, 3, 2)
# TypeError: add_numbers() takes 2 positional arguments but 3 were givenUsando Expressões como Argumentos
Argumentos não precisam ser valores simples — você pode usar qualquer expressão:
def display_total(price, quantity):
total = price * quantity
print(f"Total cost: ${total:.2f}")
# Usando expressões como argumentos
base_price = 10
display_total(base_price * 1.1, 5) # Preço com markup de 10%
display_total(15 + 5, 3 * 2) # Ambos os argumentos são expressõesOutput:
Total cost: $55.00
Total cost: $120.00O Python avalia cada expressão primeiro e depois passa os valores resultantes para a função.
Chamando Funções de Dentro de Funções
Funções podem chamar outras funções, criando uma hierarquia de operações. Esta é uma técnica poderosa que permite dividir tarefas complexas em partes menores e gerenciáveis.
Aqui está um exemplo com cálculo de área de cômodos:
def calculate_area(length, width):
return length * width
def display_room_info(room_name, length, width):
area = calculate_area(length, width)
print(f"Room: {room_name}")
print(f"Dimensions: {length} x {width}")
print(f"Area: {area} square feet")
display_room_info("Living Room", 15, 12)Output:
Room: Living Room
Dimensions: 15 x 12
Area: 180 square feetNota: Estamos usando return aqui, o que vamos explorar em detalhes na próxima seção. Por enquanto, entenda que calculate_area() envia seu resultado de volta para a função que a chamou.
Aqui está outro exemplo mostrando como funções podem se basear umas nas outras — um sistema de conversão de temperatura:
def celsius_to_fahrenheit(celsius):
return (celsius * 9/5) + 32
def format_temperature(fahrenheit):
return f"{fahrenheit:.1f}°F"
def display_temperature_conversion(celsius):
fahrenheit = celsius_to_fahrenheit(celsius)
formatted = format_temperature(fahrenheit)
print(f"{celsius}°C equals {formatted}")
# Use o sistema completo de conversão
display_temperature_conversion(25)
display_temperature_conversion(0)
display_temperature_conversion(100)Output:
25°C equals 77.0°F
0°C equals 32.0°F
100°C equals 212.0°FNeste exemplo, display_temperature_conversion() chama celsius_to_fahrenheit() para fazer a conversão, e depois chama format_temperature() para formatar o resultado. Cada função tem uma única responsabilidade clara, tornando o código fácil de entender e manter.
19.4) Usando return para Enviar Resultados de Volta
Até agora, nossas funções realizaram ações (como imprimir), mas não enviaram valores de volta para o código que as chamou. A instrução return permite que uma função compute um resultado e o envie de volta para quem chamou.
Instrução return Básica
Aqui está uma função simples que calcula e retorna um valor:
def add_numbers(a, b):
result = a + b
return result
# Capture o valor retornado
sum_value = add_numbers(5, 3)
print(f"The sum is: {sum_value}")Output:
The sum is: 8Quando o Python encontra uma instrução return, duas coisas acontecem:
- A função para de executar imediatamente (qualquer código depois de
returné ignorado) - O valor especificado é enviado de volta para quem chamou
Retornando Valores Diretamente
Você não precisa armazenar o resultado em uma variável antes de retorná-lo. Você pode retornar uma expressão diretamente:
def multiply(a, b):
return a * b
result = multiply(4, 7)
print(f"4 × 7 = {result}")Output:
4 × 7 = 28Isso é mais conciso e é o estilo preferido para cálculos simples.
Usando Valores Retornados
Quando uma função retorna um valor, você pode usar esse valor em qualquer lugar onde usaria qualquer outro valor:
def calculate_discount(price, discount_percent):
discount_amount = price * (discount_percent / 100)
return discount_amount
original_price = 100
discount = calculate_discount(original_price, 20)
# Use o valor retornado em cálculos
final_price = original_price - discount
print(f"Original price: ${original_price:.2f}")
print(f"Discount: ${discount:.2f}")
print(f"Final price: ${final_price:.2f}")Output:
Original price: $100.00
Discount: $20.00
Final price: $80.00return Sai da Função Imediatamente
Quando o Python executa uma instrução return, a função para imediatamente. Qualquer código após o return nunca é executado:
def check_age(age):
if age < 18:
return "Minor"
# Esta linha só roda se age >= 18
return "Adult"
print(check_age(15))
print(check_age(25))Output:
Minor
AdultEsse comportamento é útil para lidar com diferentes casos em uma função. Quando você determina o resultado, você pode retornar imediatamente sem precisar checar condições adicionais.
Aqui está um exemplo que demonstra como return para a execução:
def process_number(n):
if n < 0:
return "Negative"
print("This line runs for non-negative numbers")
if n == 0:
return "Zero"
print("This line runs for positive numbers")
return "Positive"
print(process_number(-5))
print()
print(process_number(0))
print()
print(process_number(10))Output:
Negative
This line runs for non-negative numbers
Zero
This line runs for non-negative numbers
This line runs for positive numbers
PositiveFunções Sem return
Se uma função não tem uma instrução return, ou se ela tem um return sem valor, a função retorna None:
def greet(name):
print(f"Hello, {name}!")
# Sem instrução return
result = greet("Alice")
print(f"The function returned: {result}")Output:
Hello, Alice!
The function returned: NoneDa mesma forma, um return “nu” (sem valor) também retorna None:
def process_data(data):
if not data:
return # Saída antecipada, retorna None
print(f"Processing: {data}")
return "Success"
result1 = process_data("")
result2 = process_data("some data")
print(f"Result 1: {result1}")
print(f"Result 2: {result2}")Output:
Processing: some data
Result 1: None
Result 2: SuccessRetornando Múltiplos Valores
Funções Python podem retornar múltiplos valores separando-os com vírgulas. O Python automaticamente empacota isso em uma tupla (tuple) (como aprendemos no Capítulo 15):
def calculate_rectangle(length, width):
area = length * width
perimeter = 2 * (length + width)
return area, perimeter
# Desempacote a tupla retornada
rect_area, rect_perimeter = calculate_rectangle(5, 3)
print(f"Area: {rect_area}")
print(f"Perimeter: {rect_perimeter}")Output:
Area: 15
Perimeter: 16Você também pode capturar a tupla como um único valor:
def get_student_info():
name = "Alice"
age = 20
grade = "A"
return name, age, grade
# Capture como uma tupla
student = get_student_info()
print(f"Student info: {student}")
print(f"Name: {student[0]}")Output:
Student info: ('Alice', 20, 'A')
Name: AliceRetornando Tipos Diferentes
Uma função pode retornar tipos diferentes de valores dependendo da situação:
def divide(a, b):
if b == 0:
return "Error: Division by zero"
return a / b
result1 = divide(10, 2)
result2 = divide(10, 0)
print(f"10 / 2 = {result1}")
print(f"10 / 0 = {result2}")Output:
10 / 2 = 5.0
10 / 0 = Error: Division by zeroEmbora isso funcione, em geral é uma prática melhor lidar com erros de forma diferente (vamos aprender sobre exceções na Parte VII). Por enquanto, entenda que funções podem retornar tipos diferentes, embora muitas vezes seja mais claro ser consistente.
19.5) Documentando Funções com Docstrings
Conforme seus programas crescem e você cria mais funções, fica crucial documentar o que cada função faz. O Python fornece uma forma embutida de documentar funções usando docstrings (documentation strings).
O Que É uma Docstring?
Uma docstring é um literal de string que aparece como a primeira instrução em uma função (ou módulo, classe ou método). Ela descreve o que a função faz, quais parâmetros ela aceita e o que retorna. Docstrings são colocadas entre aspas triplas (""" ou '''), o que permite que elas se estendam por múltiplas linhas.
def calculate_area(length, width):
"""Calculate the area of a rectangle.
Takes the length and width of a rectangle and returns the area.
"""
return length * widthPor Que Docstrings Importam
Docstrings servem a vários propósitos importantes:
- Autodocumentação (self-documentation): Elas explicam o que sua função faz sem exigir que leitores analisem o código
- Suporte da IDE: Muitas ferramentas de desenvolvimento exibem docstrings como tooltips quando você usa uma função
- Função help(): A função embutida
help()do Python exibe docstrings - Prática profissional: Código bem documentado é mais fácil de manter e compartilhar com outras pessoas
Formato Básico de Docstring
Para funções simples, uma docstring de uma linha é suficiente:
def greet(name):
"""Print a personalized greeting."""
print(f"Hello, {name}!")
# Acesse a docstring
print(greet.__doc__)Output:
Print a personalized greeting.A docstring deve ser uma descrição concisa do que a função faz, escrita como um comando ("Calculate...", "Return...", "Print...") em vez de uma descrição ("This function calculates...").
Docstrings de Múltiplas Linhas
Para funções mais complexas, use docstrings de múltiplas linhas que incluam:
- Um resumo breve na primeira linha
- Uma linha em branco
- Uma descrição mais detalhada
- Informações sobre parâmetros
- Informações sobre valores de retorno
def calculate_discount(price, discount_percent):
"""Calculate the discounted price.
Takes an original price and a discount percentage, then returns
the amount of discount that should be applied.
Parameters:
price (float): The original price before discount
discount_percent (float): The discount percentage (0-100)
Returns:
float: The discount amount in the same currency as the price
"""
return price * (discount_percent / 100)
# Use help() para ver a docstring completa
help(calculate_discount)Output:
Help on function calculate_discount in module __main__:
calculate_discount(price, discount_percent)
Calculate the discounted price.
Takes an original price and a discount percentage, then returns
the amount of discount that should be applied.
Parameters:
price (float): The original price before discount
discount_percent (float): The discount percentage (0-100)
Returns:
float: The discount amount in the same currency as the priceConvenções de Docstring
O Python tem convenções estabelecidas para escrever docstrings (documentadas na PEP 257). Aqui estão as diretrizes principais:
1. Use aspas duplas triplas: """docstring"""
def good_example():
"""This follows the convention."""
pass
def also_valid():
'''This works but is less common.'''
pass2. Docstrings de uma linha devem caber em uma linha:
def add(a, b):
"""Return the sum of a and b."""
return a + b3. Docstrings de múltiplas linhas devem ter uma linha de resumo e depois uma linha em branco:
def process_order(order_id, items):
"""Process a customer order and update inventory.
This function validates the order, checks inventory availability,
calculates the total cost, and updates the inventory database.
Parameters:
order_id (str): Unique identifier for the order
items (list): List of item dictionaries with 'product' and 'quantity'
Returns:
dict: Order summary with 'total', 'status', and 'confirmation_number'
"""
# Implementação da função aqui
passDescrevendo Parâmetros e Valores de Retorno
Ao documentar parâmetros e valores de retorno, seja específico sobre:
- Nomes de parâmetros: Correspondam aos nomes reais dos parâmetros na função
- Tipos: Que tipo de dado é esperado (vamos aprender sobre type hints no Capítulo 43)
- Propósito: Para que o parâmetro é usado
- Valor de retorno: O que a função retorna e sob quais condições
def find_student(student_id, students):
"""Find a student by ID in a list of student records.
Parameters:
student_id (int): The unique ID number of the student to find
students (list): List of student dictionaries, each containing 'id' and 'name'
Returns:
dict: The student dictionary if found, None if not found
"""
for student in students:
if student['id'] == student_id:
return student
return NoneDocstrings para Funções com Múltiplos Tipos de Retorno
Quando uma função pode retornar tipos diferentes dependendo da situação, documente todas as possibilidades:
def safe_divide(a, b):
"""Divide two numbers with error handling.
Parameters:
a (float): The dividend
b (float): The divisor
Returns:
float: The quotient if division is successful
str: An error message if b is zero
"""
if b == 0:
return "Error: Cannot divide by zero"
return a / bAcessando Docstrings
Você pode acessar a docstring de uma função de três maneiras:
1. Usando o atributo __doc__:
def example():
"""This is an example function."""
pass
print(example.__doc__)Output:
This is an example function.2. Usando a função help():
def calculate_bmi(weight, height):
"""Calculate Body Mass Index.
Parameters:
weight (float): Weight in kilograms
height (float): Height in meters
Returns:
float: BMI value
"""
return weight / (height ** 2)
help(calculate_bmi)Output:
Help on function calculate_bmi in module __main__:
calculate_bmi(weight, height)
Calculate Body Mass Index.
Parameters:
weight (float): Weight in kilograms
height (float): Height in meters
Returns:
float: BMI value3. Em ambientes de desenvolvimento interativos: A maioria das IDEs e editores de código exibem docstrings como tooltips quando você passa o mouse por cima ou digita o nome de uma função.
Quando Escrever Docstrings
Você deve escrever docstrings para:
- Todas as funções públicas (public functions): Funções que devem ser usadas por outras partes do seu programa ou por outros programadores
- Funções complexas: Qualquer função cujo propósito ou comportamento não sejam imediatamente óbvios a partir do nome e dos parâmetros
- Funções com parâmetros não óbvios: Quando nomes de parâmetros por si só não explicam completamente quais valores são esperados
Você pode pular docstrings para:
- Funções muito simples e óbvias: Funções como
def add(a, b): return a + bonde o nome e os parâmetros deixam o propósito cristalino - Funções auxiliares privadas (private helper functions): Funções internas pequenas usadas apenas dentro de uma função maior (embora até essas se beneficiem de docstrings curtas)
Docstrings Não São Comentários
Lembre que docstrings servem a um propósito diferente de comentários:
- Docstrings: Descrevem o que uma função faz e como usá-la (a interface)
- Comentários: Explicam como o código funciona internamente (a implementação)
def calculate_grade(score, total):
"""Calculate the percentage grade from a score.
Parameters:
score (int): Points earned
total (int): Total points possible
Returns:
float: The percentage grade (0-100)
"""
# Evite divisão por zero
if total == 0:
return 0.0
# Calcule a porcentagem e arredonde para 2 casas decimais
percentage = (score / total) * 100
return round(percentage, 2)A docstring diz aos usuários o que a função faz e como usá-la. Os comentários explicam detalhes específicos de implementação para alguém lendo o código.
Construindo Bons Hábitos de Documentação
Escrever docstrings claras é um hábito que vale muito a pena:
- Escreva docstrings enquanto escreve funções: Não espere para depois — documente enquanto o propósito da função está fresco na sua mente
- Mantenha docstrings atualizadas: Quando você mudar o comportamento de uma função, atualize sua docstring
- Seja conciso, mas completo: Inclua todas as informações necessárias, mas evite verbosidade desnecessária
- Use exemplos quando for útil: Para funções complexas, um exemplo de uso na docstring pode ser inestimável
Uma boa documentação deixa seu código mais profissional, mais fácil de manter e mais valioso para outras pessoas (incluindo você no futuro).