Funções

Conforme seus programas crescem, você escreverá a mesma lógica em mais de um lugar. Funções permitem escrever a lógica uma vez, dar um nome a ela e usá-la em qualquer lugar. Corrija-a em um lugar e toda chamada recebe a correção automaticamente.
def greet(name):
return f"Olá, {name}!"
print(greet("Maria")) # "Olá, Maria!"
print(greet("João")) # "Olá, João!"Escreva uma vez, use em qualquer lugar, corrija em um só lugar.
Definindo uma função
A palavra-chave def inicia uma definição de função, seguida pelo nome, parênteses, dois-pontos e um corpo indentado. Uma função não faz nada até você chamá-la. Defina-a com def, depois chame-a pelo nome com ().
def say_hello():
print("Olá!")
say_hello() # chame a funçãodef nome(): e recue o corpo abaixo. Nada acontece até você chamá-la com nome(), o def apenas a configura. E se você esquecer um return, a função silenciosamente devolve None, o que me pegou mais de uma vez no começo. Parâmetros e argumentos
Parâmetros são as entradas que sua função espera. Liste-os dentro dos parênteses. Quando você chama a função, os valores que você passa são correspondidos aos parâmetros em ordem.
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet("Maria", "Olá") # "Olá, Maria!"
greet("João", "Oi") # "Oi, João!"Parâmetro é o nome na definição da função. Argumento é o valor real que você passa quando a chama. Na prática as pessoas usam as palavras de forma intercambiável; a distinção importa principalmente ao ler documentação.
Valores padrão
Você pode dar aos parâmetros um valor padrão. Se quem chama não fornecer esse argumento, o padrão é usado. Parâmetros com padrões devem vir após parâmetros sem padrões.
def greet(name, greeting="Olá"):
print(f"{greeting}, {name}!")
greet("Maria") # "Olá, Maria!"
greet("Maria", "Oi") # "Oi, Maria!"Parâmetros com padrões devem vir após parâmetros sem padrões.
Argumentos nomeados
Ao chamar uma função, você pode nomear os argumentos. Isso torna as chamadas legíveis, especialmente para funções com muitos parâmetros, e permite que você os passe em qualquer ordem.
def describe_player(name, score, level):
print(f"{name} | Score: {score} | Level: {level}")
describe_player("Maria", 87, 5) # posicional
describe_player(name="Maria", level=5, score=87) # nomeado, qualquer ordem
describe_player("Maria", level=5, score=87) # misto: posicional primeiroscore=87) e a chamada se explica, além disso você pode passá-los em qualquer ordem. A única regra: argumentos posicionais vêm antes dos nomeados. Ótimo para funções com um monte de parâmetros. Valores de retorno
return envia um valor de volta para quem chamou. Sem return, uma função devolve None. Uma vez que return é executado, a função sai imediatamente. Qualquer código após ele naquele bloco é pulado.
def add(a, b):
return a + b
result = add(3, 4) # result = 7
print(result)return também sai da função imediatamente. Qualquer código após ele naquele bloco não é executado.
return devolve um valor para quem chamou a função, e a função para bem ali, qualquer coisa depois dela é pulada. Deixe de lado return e você recebe None de volta. print mostra um valor, return o devolve para usar, levou um tempo para eu sentir essa diferença. Retornando múltiplos valores
Python permite que você retorne múltiplos valores separando-os com vírgulas. Quem chama os recebe como uma tupla e pode desempacotá-los em nomes separados em uma linha.
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([3, 7, 1, 9, 4])
print(low, high) # 1 9A sintaxe low, high = ... é desempacotamento: Python atribui cada valor retornado ao nome correspondente.
low, high = min_max(...), um nome por valor. Útil sempre que uma função naturalmente produz mais de uma resposta. Escopo
Variáveis criadas dentro de uma função existem apenas dentro dessa função. Você não pode vê-las de fora. Variáveis definidas fora de todas as funções são visíveis em qualquer lugar, mas você não pode mudá-las de dentro de uma função sem uma declaração explícita.
global primeiro. Alcance isso quase nunca: passe valores, retorne resultados, e a função permanece simples de seguir. def calculate():
result = 42 # local para essa função
return result
calculate()
print(result) # NameError, result não existe aquicount = 0
def increment():
global count # declare que quer modificar o global
count += 1
increment()
print(count) # 1Usar global deve ser um último recurso. Torna o código mais difícil de raciocinar. Prefira passar valores dentro e retorná-los. Escopo é construído diretamente sobre como atribuição vincula um nome a um valor, coberto no capítulo Variáveis e tipos.
*args e **kwargs
Às vezes você não sabe quantos argumentos uma função receberá. *args coleta qualquer número de argumentos posicionais em uma tupla. **kwargs coleta qualquer número de argumentos nomeados em um dicionário. Os nomes args e kwargs são convenções; os asteriscos é que importam.
def total(*args):
return sum(args)
total(1, 2, 3) # 6
total(1, 2, 3, 4, 5) # 15def display(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
display(name="Maria", score=87, level=5)Você pode misturá-los com parâmetros regulares. Parâmetros regulares vêm primeiro:
def describe(title, *tags, **metadata):
print(f"{title} | tags: {tags} | meta: {metadata}")
describe("Introdução a Python", "iniciante", "python", author="Maria", year=2024)*args recolhe qualquer número de argumentos posicionais extras como uma tupla, **kwargs recolhe nomeados extras como um dict. As palavras args e kwargs são apenas convenção, o * e ** fazem o trabalho real. Útil quando você não consegue dizer antecipadamente quantas coisas entram. Docstrings
Uma docstring é uma string no topo de uma função que descreve o que ela faz. Editores Python e ferramentas a usam para mostrar ajuda quando você passa o mouse sobre uma chamada de função. Use aspas triplas e escreva uma linha para funções simples.
def normalise(value, min_val, max_val):
"""Escale um valor para o intervalo 0-1 dados o min e max conhecidos."""
return (value - min_val) / (max_val - min_val)def build_url(base, version, resource, *, secure=True):
"""
Constrói uma URL de endpoint da API.
Retorna uma string de URL totalmente qualificada. Se secure for False,
a URL usará http em vez de https.
"""
scheme = "https" if secure else "http"
base = base.replace("https://", "").replace("http://", "")
return f"{scheme}://{base}/{version}/{resource}"Escreva uma docstring para qualquer função cujo propósito não seja claro pelo seu nome e assinatura.
Anotações de tipo
Anotações de tipo permitem que você anote quais tipos uma função espera e retorna. Python não as aplica em tempo de execução, mas editores as usam para pegar erros antes de você executar qualquer coisa. O -> antes dos dois-pontos especifica o tipo de retorno.
def greet(name: str, score: int) -> str:
return f"{name} scored {score}"def log(message: str) -> None:
print(f"[LOG] {message}")def top_scores(scores: list[int], n: int) -> list[int]:
return sorted(scores, reverse=True)[:n]Anotações de tipo são opcionais mas valiosas em qualquer função que será chamada de múltiplos lugares. Elas são documentação que ferramentas podem verificar.
name: str e -> str para o retorno. Python não as aplicará quando é executado, mas seu editor as lê e o avisa antes de você acertar executar. Pense nelas como notas que as ferramentas podem verificar. Funções como valores
Funções em Python são valores, como strings ou números. Você pode atribuí-las a variáveis e passá-las para outras funções. É assim que sorted() aceita uma função key=.
def double(x):
return x * 2
def apply(func, value):
return func(value)
apply(double, 5) # 10Passar funções como argumentos mostra-se constantemente com sorted(), map() e filter(). Você também verá em capítulo Lambdas e compreensões.
Na prática
Duas funções que funcionam juntas: letter_grade converte uma pontuação para uma letra, e summarise a chama para cada pontuação em uma lista:
def letter_grade(score: int) -> str:
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "F"
def summarise(scores: list[int]) -> None:
total = sum(scores)
avg = total / len(scores)
grades = []
for s in scores:
grades.append(letter_grade(s))
print(f"Média: {avg:.1f}")
print(f"Notas: {', '.join(grades)}")
summarise([87, 92, 74, 65, 91])
