Pular para o conteúdo

    Capítulo 17, Básico

    Funções

    Uma função dá nome a um pedaço de lógica. Escrever boas funções é o que separa um script que funciona de um programa que dá para manter.

    Código deste capítulo: basico/cap17_funcoes.py

    Definir, chamar e devolver

    Uma função se define com def, recebe parâmetros e devolve um valor com return. Se não houver return, ela devolve None:

    basico/cap17_funcoes.pylinhas 10 a 20
    def saudacao(nome):
        """Devolve uma saudação."""
        return f"Olá, {nome}!"
    
    
    def sem_retorno():
        pass
    
    
    print(saudacao("Ana"))
    print(sem_retorno())
    
    Saída
    Olá, Ana!
    None
    

    Uma confusão comum: print mostra na tela, return devolve o valor para quem chamou. Uma função que só imprime não pode ter o resultado usado em outra conta.

    Parâmetros e argumentos

    Parâmetro é o nome na definição. Argumento é o valor passado na chamada. Há quatro formas de passar:

    • Posicional: a ordem importa.
    • Nomeada: nome=valor, em qualquer ordem.
    • Padrão: o parâmetro tem um valor caso não seja passado.
    • Somente posicional (/) e somente nomeado (*): você controla como a função pode ser chamada.
    basico/cap17_funcoes.pylinhas 25 a 34
    def criar_usuario(nome, /, email, *, ativo=True):
        return {"nome": nome, "email": email, "ativo": ativo}
    
    
    print(criar_usuario("Ana", "ana@exemplo.com"))
    print(criar_usuario("Bia", email="bia@exemplo.com", ativo=False))
    try:
        criar_usuario(nome="Caio", email="c@exemplo.com")
    except TypeError as erro:
        print(erro)
    
    Saída
    {'nome': 'Ana', 'email': 'ana@exemplo.com', 'ativo': True}
    {'nome': 'Bia', 'email': 'bia@exemplo.com', 'ativo': False}
    criar_usuario() got some positional-only arguments passed as keyword arguments: 'nome'
    

    Eu uso parâmetros somente nomeados (depois do *) para opções booleanas, porque formatar(texto, True) não diz nada e formatar(texto, maiusculo=True) diz tudo.

    *args e **kwargs

    Para aceitar uma quantidade variável de argumentos, *args junta os posicionais em uma tupla e **kwargs junta os nomeados em um dicionário. Na chamada, o mesmo símbolo faz o caminho inverso: desempacota:

    basico/cap17_funcoes.pylinhas 39 a 54
    def somar(*numeros):
        return sum(numeros)
    
    
    def descrever(**atributos):
        for chave, valor in atributos.items():
            print(f"{chave}: {valor}")
    
    
    print(somar(1, 2, 3, 4))
    descrever(nome="Ana", cidade="Recife")
    
    valores = [10, 20, 30]
    print(somar(*valores))
    dados = {"nome": "Bia", "cidade": "Natal"}
    descrever(**dados)
    
    Saída
    10
    nome: Ana
    cidade: Recife
    60
    nome: Bia
    cidade: Natal
    

    Vários valores de retorno

    Uma função pode devolver uma tupla, e quem chama desempacota na hora:

    basico/cap17_funcoes.pylinhas 59 a 64
    def minimo_maximo(numeros):
        return min(numeros), max(numeros)
    
    
    menor, maior = minimo_maximo([4, 8, 2, 9])
    print(menor, maior)
    
    Saída
    2 9
    

    Funções são objetos

    Em Python, uma função é um valor como qualquer outro: pode ser guardada em variável e passada como argumento. Essa ideia é a base dos decoradores e da programação funcional que vêm no nível intermediário:

    basico/cap17_funcoes.pylinhas 69 a 74
    def aplicar(funcao, valor):
        return funcao(valor)
    
    
    print(aplicar(len, "python"))
    print(aplicar(str.upper, "python"))
    
    Saída
    6
    PYTHON
    

    Documentação e type hints

    A docstring explica o contrato. As anotações de tipo (type hints) o tornam legível por ferramentas. O Python não verifica as anotações ao executar:

    basico/cap17_funcoes.pylinhas 79 a 85
    def soma(a: int, b: int) -> int:
        """Soma dois inteiros e devolve o resultado."""
        return a + b
    
    
    print(soma(2, 3))
    print(soma("a", "b"))
    
    Saída
    5
    ab
    

    A segunda chamada funciona e junta duas strings, apesar de a anotação dizer int. Quem verifica é uma ferramenta externa, como o mypy, que eu apresento no nível intermediário.

    Exercício 1

    Média de quantos números quiser

    Escreva media(*numeros) que devolva a média aritmética.

    Exercício 2

    Nome completo com opção

    Escreva formatar_nome(nome, sobrenome, *, maiusculo=False).