Funções
Conforme seus programas crescem, você vai escrever a mesma lógica em mais de um lugar. Funções permitem que você escreva a lógica uma vez, dê um nome a ela e a use em qualquer lugar. Corrija em um só lugar e toda chamada recebe a correção automaticamente.
def greet(name):
return f"Hello, {name}!"
print(greet("Alice")) # "Hello, Alice!"
print(greet("Bob")) # "Hello, Bob!"Escreva uma vez, use em qualquer lugar, corrija em um só ponto.
Definindo uma função
A palavra-chave def inicia uma definição de função, seguida do nome, parênteses, dois-pontos e um corpo indentado. Uma função não faz nada até que você a chame. Defina-a com def, depois a chame pelo nome com ().
def say_hello():
print("Hello!")
say_hello() # chama a funçãodef nome(): e indente o corpo abaixo. Nada acontece até você chamá-la com nome(), o def só faz a preparação. E se você esquecer o return, a função devolve None silenciosamente, o que já 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 na ordem.
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet("Alice", "Hello") # "Hello, Alice!"
greet("Bob", "Hi") # "Hi, Bob!"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 os termos de forma intercambiável; a distinção importa principalmente ao ler documentação.
Valores padrão
Você pode dar a um parâmetro um valor padrão. Se quem chama não fornecer esse argumento, o padrão é usado. Parâmetros com valores padrão devem vir depois dos parâmetros sem valores padrão.
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
greet("Alice") # "Hello, Alice!"
greet("Alice", "Hi") # "Hi, Alice!"Parâmetros com valores padrão devem vir depois dos parâmetros sem valores padrão.
Argumentos nomeados
Ao chamar uma função, você pode nomear os argumentos. Isso torna as chamadas mais legíveis, especialmente para funções com muitos parâmetros, e permite passá-los em qualquer ordem.
def describe_player(name, score, level):
print(f"{name} | Score: {score} | Level: {level}")
describe_player("Alice", 87, 5) # posicional
describe_player(name="Alice", level=5, score=87) # nomeado, em qualquer ordem
describe_player("Alice", level=5, score=87) # misto: posicional primeiroscore=87) e a chamada se explica sozinha, além de permitir passá-los em qualquer ordem. A única regra: qualquer argumento posicional vem antes dos nomeados. Ótimo para funções com uma pilha de parâmetros. Valores de retorno
return envia um valor de volta para quem chamou a função. Sem return, uma função devolve None. Assim que o return é executado, a função é encerrada imediatamente. Qualquer código depois dele naquele bloco é ignorado.
def add(a, b):
return a + b
result = add(3, 4) # result = 7
print(result)return também encerra a função imediatamente. Qualquer código depois dele naquele bloco não é executado.
return devolve um valor para quem chamou a função, e a função para ali mesmo, qualquer coisa depois dele é ignorada. Se você não colocar return, você recebe None de volta. print mostra um valor, return devolve ele para uso, demorei um tempo para sentir essa diferença. Retornando múltiplos valores
O Python permite retornar múltiplos valores separando-os com vírgulas. Quem chama a função os recebe como uma tupla e pode desempacotá-los em nomes separados em uma única 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: o 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 daquela função. Você não pode vê-las de fora. Variáveis definidas fora de todas as funções são visíveis em todo lugar, mas você não pode alterá-las de dentro de uma função sem uma declaração explícita.
global antes. Use isso quase nunca: passe valores para dentro, retorne resultados para fora, e a função continua simples de acompanhar. def calculate():
result = 42 # local a esta função
return result
calculate()
print(result) # NameError, result não existe aqui foracount = 0
def increment():
global count # declara que você quer modificar a global
count += 1
increment()
print(count) # 1Usar global deve ser o último recurso. Isso torna o código mais difícil de entender. Prefira passar valores como entrada e retorná-los como saída. Escopo se apoia diretamente em como a atribuição vincula um nome a um valor, assunto abordado no capítulo Variáveis e tipos.
*args e **kwargs
Às vezes você não sabe quantos argumentos uma função vai receber. *args coleta qualquer quantidade de argumentos posicionais em uma tupla. **kwargs coleta qualquer quantidade 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="Alice", score=87, level=5)Você pode misturá-los com parâmetros normais. Os parâmetros normais vêm primeiro:
def describe(title, *tags, **metadata):
print(f"{title} | tags: {tags} | meta: {metadata}")
describe("Python intro", "beginner", "python", author="Alice", year=2024)*args junta qualquer quantidade de argumentos posicionais extras como uma tupla, **kwargs junta os nomeados extras como um dict. As palavras args e kwargs são só convenção, o * e o ** é que fazem o trabalho de fato. Útil quando você não sabe de antemão quantas coisas vão chegar. Docstrings
Uma docstring é uma string no topo de uma função que descreve o que ela faz. Editores e ferramentas do Python 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):
"""Escala um valor para a faixa 0-1 dado o mínimo e o máximo conhecidos."""
return (value - min_val) / (max_val - min_val)def build_url(base, version, resource, *, secure=True):
"""
Constrói a URL de um 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 a partir do nome e da assinatura.
Type hints
Type hints permitem que você anote quais tipos uma função espera e retorna. O Python não os impõe em tempo de execução, mas editores os usam para identificar erros antes que você execute 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]Type hints são opcionais, mas valiosos em qualquer função que será chamada de vários lugares. Eles são documentação que ferramentas podem verificar.
name: str e -> str para o retorno. O Python não vai impor eles ao executar, mas seu editor os lê e te avisa antes de você rodar o código. Pense neles como anotações que as ferramentas conseguem checar. 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 em key=.
def double(x):
return x * 2
def apply(func, value):
return func(value)
apply(double, 5) # 10Passar funções como argumentos aparece o tempo todo com sorted(), map() e filter(). Você também vai ver isso no capítulo Lambdas e comprehensions.
key= para sorted(). Achei estranho no começo, depois fez sentido e passou a aparecer em todo lugar. Na prática
Duas funções que trabalham juntas: letter_grade converte uma nota em uma letra, e summarise a chama para cada nota 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"Average: {avg:.1f}")
print(f"Grades: {', '.join(grades)}")
summarise([87, 92, 74, 65, 91])
