Skip to content
This page has been auto-translated and may contain errors.View in English

Funções

À medida que seus programas crescem, você acabará escrevendo 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 todos os lugares. Corrija em um único lugar e toda chamada recebe a correção automaticamente.

Funções são a principal unidade de reutilização de código e abstração. Elas encapsulam um comportamento, dão um nome a ele, definem uma interface clara (parâmetros e valor de retorno) e tornam-no chamável de qualquer lugar. Funções com nomes bem escolhidos também servem como documentação: validate_email() te diz o que um bloco de código faz sem precisar lê-lo.

Em Python, def cria um objeto função e o vincula a um nome no escopo atual. Funções são objetos de primeira classe: podem ser atribuídas a variáveis, armazenadas em coleções, passadas como argumentos e retornadas de outras funções. Closures capturam variáveis livres do escopo envolvente. Compreender isso torna a programação de ordem superior natural.

python
def greet(name):
    return f"Hello, {name}!"

print(greet("Ana"))    # "Hello, Ana!"
print(greet("Bruno"))  # "Hello, Bruno!"

Escreva uma vez, use em todo lugar, conserte em um único lugar.

Definindo uma função

A palavra-chave def inicia a definição de uma função, seguida pelo nome, parênteses, dois-pontos e um corpo indentado. Uma função não faz nada até ser chamada. Defina-a com def, e então chame-a pelo nome com ().

def é uma instrução que cria um objeto função e o vincula ao nome dado no escopo atual. O corpo não é executado no momento da definição; ele só é executado quando a função é chamada. Funções sem uma instrução return retornam implicitamente None.

def é uma instrução composta que compila o corpo da função em um objeto código e vincula um novo objeto função ao nome no namespace atual. O objeto função armazena uma referência ao seu objeto código, seus valores de argumentos padrão e uma referência ao escopo envolvente (para closures). O corpo só é executado na invocação.

python
def say_hello():
    print("Hello!")

say_hello()   # chama a funçã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.

Parâmetros definem a interface de uma função. Argumentos são os valores concretos passados no momento da chamada. Argumentos posicionais são correspondidos por posição; argumentos nomeados são correspondidos por nome. Valores padrão tornam os parâmetros opcionais.

Python tem quatro tipos de parâmetros: posicional-ou-nomeado (o padrão), exclusivamente nomeado (após *), exclusivamente posicional (antes de /, Python 3.8+) e variádico (*args, **kwargs). No momento da chamada, argumentos posicionais são vinculados da esquerda para a direita; argumentos nomeados são vinculados por nome. Conflitos geram TypeError. Valores padrão são avaliados uma vez no momento da definição da função, não em cada chamada.

python
def greet(name, greeting):
    print(f"{greeting}, {name}!")

greet("Ana", "Hello")    # "Hello, Ana!"
greet("Bruno", "Hi")     # "Hi, Bruno!"

Parâmetros vs argumentos

Parâmetro é o nome na definição da função. Argumento é o valor real que você passa quando chama a função. Na prática, as pessoas usam as palavras de forma intercambiável. Apenas tenha consciência da distinção ao ler documentação.

Valores padrão

Você pode dar a um parâmetro um valor padrão. Se o chamador não fornecer aquele argumento, o padrão é usado. Parâmetros com padrões devem vir depois de parâmetros sem padrões.

Valores padrão tornam os parâmetros opcionais. Eles são avaliados uma vez no momento da definição, não em cada chamada. Isso importa para padrões mutáveis: def f(items=[]) compartilha a mesma lista entre todas as chamadas. A solução é usar None como padrão e criar a lista dentro do corpo da função.

Valores padrão são armazenados no objeto função como f.__defaults__ (posicionais) e f.__kwdefaults__ (exclusivamente nomeados). Eles são avaliados uma vez quando def é executado, não por chamada. A armadilha do padrão mutável (def f(x=[])) é uma clássica pegadinha do Python: a lista é criada uma vez e mutada no lugar entre as chamadas. A correção idiomática: def f(x=None): if x is None: x = [].

python
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Ana")           # "Hello, Ana!"
greet("Ana", "Hi")     # "Hi, Ana!"

Parâmetros com padrões devem vir depois de 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.

Argumentos nomeados tornam as chamadas de função autodocumentadas. Você pode misturar posicionais e nomeados: argumentos posicionais devem vir primeiro. Para funções com flags booleanas ou muitos parâmetros de tipos semelhantes, argumentos nomeados previnem erros silenciosos por passar argumentos na ordem errada.

Argumentos nomeados são vinculados por nome, não por posição. Argumentos posicionais devem preceder argumentos nomeados no momento da chamada. Passar o mesmo argumento tanto posicionalmente quanto por nome gera TypeError. Para forçar argumentos exclusivamente nomeados, coloque-os após um * simples na lista de parâmetros: def f(a, *, b) torna b exclusivamente nomeado.

python
def describe_player(name, score, level):
    print(f"{name} | Score: {score} | Level: {level}")

describe_player("Ana", 87, 5)                       # posicional
describe_player(name="Ana", level=5, score=87)      # nomeado, qualquer ordem
describe_player("Ana", level=5, score=87)           # misto: posicionais primeiro

Valores de retorno

return envia um valor de volta ao chamador. Sem return, uma função devolve None. Quando return é executado, a função sai imediatamente. Qualquer código após ele naquele bloco é ignorado.

return sai da função e passa um valor ao chamador. Uma função sem um return explícito retorna implicitamente None. return pode aparecer em qualquer lugar no corpo da função e pode ser usado várias vezes; o primeiro alcançado encerra a função. Isso torna retornos antecipados úteis para cláusulas de guarda.

return emite um bytecode RETURN_VALUE que desempilha o topo da pilha e o entrega ao frame do chamador. Uma função que termina sem retornar explicitamente retorna None. Múltiplas instruções return são aceitáveis e frequentemente mais limpas do que um único retorno com condições complexas (o padrão "early return"). return dentro de um bloco try ainda executa qualquer cláusula finally associada.

python
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.

Retornando múltiplos valores

Python permite retornar múltiplos valores separando-os com vírgulas. O chamador os recebe como uma tupla e pode desempacotá-los em nomes separados em uma única linha.

Retornar múltiplos valores com uma vírgula os empacota em uma tupla. O chamador desempacota com nomes correspondentes. Isso é Python idiomático para funções que naturalmente produzem mais de um resultado. Não é um recurso especial; é apenas empacotamento e desempacotamento de tuplas.

return a, b empacota os valores em uma tupla via empacotamento implícito. O chamador desempacota com x, y = f(), o que chama __iter__ na tupla retornada. Para clareza em type hints, anote o tipo de retorno como tuple[int, str] ou use uma named tuple. Retornar uma tupla simples é adequado para poucos elementos; para mais de dois ou três valores, considere uma named tuple ou dataclass.

python
def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([3, 7, 1, 9, 4])
print(low, high)   # 1 9

A sintaxe low, high = ... é desempacotamento: Python atribui cada valor retornado ao nome correspondente.

Escopo

Variáveis criadas dentro de uma função existem apenas dentro dela. Você não pode vê-las de fora. Variáveis definidas fora de todas as funções são visíveis em todos os lugares, mas você não pode alterá-las de dentro de uma função sem uma declaração explícita.

Python tem escopo local (dentro de uma função), escopo envolvente (em uma função externa para funções aninhadas), escopo global (o nível do módulo) e escopo built-in. A busca de nomes segue a regra LEGB nessa ordem. Variáveis locais sombreiam variáveis externas de mesmo nome. global declara que um nome se refere à vinculação no nível do módulo.

A resolução de nomes LEGB do Python: Local, Enclosing (closure), Global (módulo), Built-in. Cada def cria um novo namespace local. Ler uma variável global funciona automaticamente; escrever requer global x para evitar criar um sombreamento local. nonlocal x acessa o escopo envolvente mais próximo (não global), permitindo que closures mutem variáveis capturadas. Usar global em excesso torna o código difícil de raciocinar; prefira parâmetros e valores de retorno.

python
def calculate():
    result = 42   # local a esta função
    return result

calculate()
print(result)   # NameError, result não existe aqui fora
python
count = 0

def increment():
    global count    # declara que você quer modificar o global
    count += 1

increment()
print(count)   # 1

Usar global deve ser um último recurso. Torna o código mais difícil de raciocinar. Prefira passar valores como argumentos e retorná-los.

*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; o que importa são os asteriscos.

*args coleta argumentos posicionais excedentes em uma tupla. **kwargs coleta argumentos nomeados excedentes em um dict. Ambos podem ser combinados com parâmetros normais. Parâmetros normais vêm primeiro, depois *args, depois parâmetros exclusivamente nomeados, depois **kwargs. São úteis para funções wrapper que repassam argumentos para outra função.

*args cria uma tuple a partir dos argumentos posicionais restantes. **kwargs cria um dict a partir dos argumentos nomeados restantes. Ordem dos parâmetros: posicional-ou-nomeado, *args, exclusivamente nomeado, **kwargs. Em pontos de chamada, *iterable desempacota argumentos posicionais e **mapping desempacota argumentos nomeados. Eles são simétricos: * em uma assinatura coleta; * em um ponto de chamada desempacota.

python
def total(*args):
    return sum(args)

total(1, 2, 3)         # 6
total(1, 2, 3, 4, 5)   # 15
python
def display(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

display(name="Ana", score=87, level=5)

Você pode misturá-los com parâmetros normais. Parâmetros normais vêm primeiro:

python
def describe(title, *tags, **metadata):
    print(f"{title} | tags: {tags} | meta: {metadata}")

describe("Python intro", "beginner", "python", author="Ana", year=2024)

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.

Docstrings são armazenadas como f.__doc__ e exibidas por help(). A convenção é uma linha de resumo, opcionalmente seguida por uma linha em branco e mais detalhes. Para funções de uso público, uma docstring é documentação que as ferramentas podem exibir; ela não é opcional em nada que seja chamado de múltiplos lugares.

Docstrings são literais de string colocados como a primeira instrução do corpo de uma função, classe ou módulo. Elas são armazenadas como __doc__ no objeto. A PEP 257 define convenções. Ferramentas como Sphinx, pydoc e IDEs dependem de __doc__. Para informações de tipo em docstrings, use o estilo Google, NumPy ou Sphinx; type hints na assinatura são preferíveis a anotações de tipo na docstring para código moderno.

python
def normalise(value, min_val, max_val):
    """Scale a value to the 0-1 range given the known min and max."""
    return (value - min_val) / (max_val - min_val)
python
def build_url(base, version, resource, *, secure=True):
    """
    Build an API endpoint URL.

    Returns a fully-qualified URL string. If secure is False,
    the URL will use http instead of 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 que não seja obviamente autoexplicativa pelo seu nome e assinatura.

Type hints

Type hints permitem que você anote quais tipos uma função espera e retorna. Python não os força em tempo de execução, mas editores os usam para detectar erros antes de você executar qualquer coisa. O -> antes dos dois-pontos especifica o tipo de retorno.

Type hints são documentação que ferramentas verificam. Editores e verificadores de tipo (mypy, pyright) os usam para detectar incompatibilidades de tipo antes do runtime. Não têm efeito em tempo de execução no Python padrão. -> None é a anotação correta para funções sem valor de retorno. Para contêineres genéricos, use list[int], dict[str, int] (Python 3.9+).

Type hints são processados por typing.get_type_hints() em runtime, mas não têm efeito direto na execução. Verificadores estáticos de tipo os analisam antes do runtime. A PEP 484 introduziu o sistema de anotações; a PEP 585 permitiu genéricos built-in como list[int] sem imports de typing no Python 3.9+. -> None em uma assinatura de função sinaliza tanto "não retorna nada" quanto "não deve ser usado em um contexto de expressão". Para tipos complexos, typing.Protocol, typing.TypeVar e typing.overload oferecem todo o poder da tipagem estática.

python
def greet(name: str, score: int) -> str:
    return f"{name} scored {score}"
python
def log(message: str) -> None:
    print(f"[LOG] {message}")
python
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 múltiplos lugares. São documentação que as ferramentas podem verificar.

Funções como valores

Funções em Python são valores, assim 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=.

Funções são objetos de primeira classe: têm um tipo (function), podem ser armazenadas em variáveis e coleções, e podem ser passadas como argumentos ou retornadas como valores. Esta é a base de funções de ordem superior como sorted(key=...), map() e filter().

Funções são objetos do tipo function com atributos: __name__, __doc__, __annotations__, __defaults__, __code__ e __closure__. São passadas por referência, não copiadas. Retornar uma função de outra função cria uma closure se a função interna referencia variáveis do escopo externo: essas variáveis são armazenadas em f.__closure__.

python
def double(x):
    return x * 2

def apply(func, value):
    return func(value)

apply(double, 5)   # 10

Passar funções como argumentos aparece constantemente com sorted(), map() e filter(). Você também verá isso no capítulo Lambda, comprehensions e zip.

Na prática

Duas funções que trabalham juntas: letter_grade converte uma pontuação em uma letra, e summarise a chama para cada pontuação em uma lista:

python
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 = [letter_grade(s) for s in scores]
    print(f"Average: {avg:.1f}")
    print(f"Grades: {', '.join(grades)}")

summarise([87, 92, 74, 65, 91])

Um formatador de log e um processador de arquivos que o utiliza, com um parâmetro padrão dry_run que previne efeitos colaterais a menos que seja explicitamente desabilitado:

python
def format_log(level: str, message: str) -> str:
    return f"[{level.upper():5}] {message}"

def process_file(path: str, dry_run: bool = True) -> bool:
    print(format_log("info", f"Processing {path}"))
    if dry_run:
        print(format_log("info", "Dry run, no changes made"))
        return True
    return True

process_file("report.csv")
process_file("report.csv", dry_run=False)

Um normalizador de valor único e um normalizador de coluna construído sobre ele, com type hints e uma docstring. A função de coluna calcula a faixa uma vez e reutiliza a função escalar para cada item:

python
def normalise(value: float, min_val: float, max_val: float) -> float:
    """Scale value to the 0-1 range given known min and max."""
    if max_val == min_val:
        return 0.0
    return (value - min_val) / (max_val - min_val)

def normalise_column(values: list[float]) -> list[float]:
    """Normalise an entire column of values."""
    lo, hi = min(values), max(values)
    return [normalise(v, lo, hi) for v in values]

raw = [10.0, 25.0, 5.0, 40.0, 15.0]
print(normalise_column(raw))

Type hints aqui servem a dois propósitos: documentam o que a função espera, e permitem que um verificador de tipo detecte chamadores que passam uma lista de strings por engano.