Fundamentos
return em Python: devolvendo um ou vários valores
Entenda o return em Python: devolver um valor, a diferença para print, sair da função cedo, o None e como devolver vários valores com tuplas.
Por Prof. Rodrigo Faustino · Atualizado em · 14 min de leitura
O return encerra a função e entrega um valor a quem a chamou. Esse valor pode ser guardado numa variável, usado numa conta, testado num if ou passado para outra função, e é o que diferencia uma função que apenas faz uma coisa de uma função que calcula uma resposta. Uma função pode devolver um valor só, vários valores de uma vez, em forma de tupla, ou nada, caso em que entrega None.
Nos dois artigos anteriores as funções mostravam o resultado com print. Isso resolve o exercício do momento, mas deixa o resultado preso na tela: ninguém consegue somá-lo, compará-lo ou reaproveitá-lo. Aqui veremos como devolver, onde a função termina, o que acontece quando não há return, como devolver dois ou três valores de uma vez e como isso aparece nos programas de ESP32.
Você já recebe valores devolvidos
Desde o segundo artigo da série você usa funções que devolvem. O int("12") entrega o número 12, o len(texto) entrega o tamanho, e o input() entrega o que foi digitado. Em todos, o que aparece depois da chamada é um valor que você guarda ou usa:
idade = int(input("idade: "))
total = len("python") + 1Na ESP32 também: botao.value() entrega 0 ou 1 e adc.read() entrega a leitura. Escrever a sua própria função que devolve é fazer o mesmo no outro sentido: você decide o que sai.
Da ementa ao semestre planejado
- Plano de ensino e calendário montados sozinhos
- Diário de aulas pronto para colar no SIGA
- Slides e listas de exercícios com gabarito
Versão Community grátis · Windows
return: entregar o resultado
A palavra return vem seguida da expressão cujo valor será entregue:
def dobro(n):
return n * 2
print(dobro(4))
x = dobro(5)
print(x)
print(dobro(3) + dobro(4))
print(dobro(dobro(2)))
print("fim")A saída é 8, 10, 14, 8 e fim. A chamada dobro(4) é substituída pelo valor 8 no lugar onde foi escrita, e por isso pode ser impressa, guardada em x, somada a outra chamada ou usada como argumento de uma terceira. Na última linha, dobro(dobro(2)) primeiro calcula dobro(2), que dá 4, e depois dobro(4), que dá 8. Quem lê de dentro para fora acerta a ordem.
return não é print
A confusão mais comum do módulo é achar que return e print fazem a mesma coisa porque, no teste do aluno, os dois "mostram o número". O print escreve na tela e acabou: o que ele entrega à função é None. O return não escreve nada, e o valor fica disponível para quem chamou.
def dobro_print(n):
print(n * 2)
def dobro_return(n):
return n * 2
a = dobro_print(4)
print("a vale", a)
b = dobro_return(4)
print("b vale", b)
print(dobro_return(4) + 1)
dobro_return(4)
print("fim")A saída é 8, a vale None, b vale 8, 9 e fim. O primeiro 8 veio de dentro de dobro_print, quando foi chamada. A variável a ficou com None. A dobro_return não mostrou nada, e b ficou com 8. A conta dobro_return(4) + 1 deu 9. A última chamada, dobro_return(4) sozinha, não imprime nada: o valor foi entregue e ninguém o guardou, então ele se perdeu. É por isso que funções que devolvem quase sempre aparecem dentro de um print, de uma atribuição ou de outra expressão.
Quando uma função só imprime, ela não pode ser usada numa conta:
def dobro(n):
print(n * 2)
print(dobro(3) + dobro(4))6
8
Traceback (most recent call last):
File "main.py", line 4, in <module>
TypeError: unsupported types for __add__: 'NoneType', 'NoneType'Os dois números 6 e 8 aparecem porque as chamadas rodaram e imprimiram. Depois o Python tenta somar o que elas devolveram, que é None nas duas, e falha. O Python do computador escreve a mensagem como unsupported operand type(s) for +: 'NoneType' and 'NoneType'. Sempre que aparecer NoneType numa mensagem, procure uma função que devia ter um return.
Uma regra prática: se o resultado será usado depois, devolva. Se o objetivo é mostrar, imprima, e de preferência fora da função, no programa principal, que decide como mostrar.
O return encerra a função
Quando o Python chega a um return, a função acaba ali. As linhas seguintes do corpo não rodam, e o valor volta para a chamada.
def f():
print("antes")
return 1
print("depois")
print(f())
def g(n):
if n > 0:
return "positivo"
print("nao positivo")
print(g(3))
print(g(-1))A saída é antes, 1, positivo, nao positivo e None. Na função f, o print("depois") nunca roda, como já acontecia com o break e o continue. Na g, o return fica dentro do if: com 3 a função devolve na hora, e com -1 passa direto, imprime o aviso e termina sem devolver nada, o que entrega None.
Esse comportamento permite um estilo muito útil, o de testar os casos um por um e devolver assim que um servir. A figura mostra a função classificar em três chamadas, e cada uma termina no primeiro return que alcança:
def classificar(n):
if n < 0:
return "negativo"
if n == 0:
return "zero"
return "positivo"
print(classificar(-5))
print(classificar(0))
print(classificar(7))A saída é negativo, zero e positivo. Repare que não há else nem elif: depois de um return, o que vem abaixo só roda se o anterior não serviu, então o else seria redundante. É o mesmo raciocínio da escada do elif, com o fluxo cortado pelo return. A função fica mais plana, com menos níveis de recuo.
O mesmo vale para a função que escolhe entre dois valores, como a do desafio Maior de Dois:
def maior(a, b):
if a > b:
return a
return b
print(maior(10, 20))
print(maior(45, 12))
print(maior(7, 7))A saída é 20, 45 e 7. Com os dois iguais, o a > b é falso e a função devolve b, que vale o mesmo.
Devolver um booleano
Uma função que responde sim ou não devolve True ou False. A expressão do return pode ser a própria comparação, sem if:
def eh_par(n):
return n % 2 == 0
print(eh_par(4))
print(eh_par(7))
if eh_par(10):
print("10 e par")
for n in range(1, 6):
if eh_par(n):
print(n, "par")A saída é True, False, 10 e par, 2 par e 4 par. Escrever if n % 2 == 0: return True e depois else: return False funciona, mas dá mais linhas para o mesmo efeito. Como a chamada eh_par(n) já é um booleano, ela cabe direto num if, como as condições dos artigos sobre tabelas-verdade. Esse padrão aparece no desafio Função eh_par. Funções que respondem sim ou não costumam ter nomes de pergunta, como eh_par, esta_ligado ou apertado.
A IA que lembra da sua vida e mora no seu computador
- Memória de longo prazo com a fonte de cada resposta
- Funciona offline: seus dados ficam no seu PC
- Lê PDFs, slides, fotos e gravações de reunião
Plano Essencial grátis para sempre
return dentro de um laço
Um return dentro de um for sai da função inteira, não só do laço. Isso torna a busca mais curta que a do break com else, do artigo sobre break, continue e else:
def primeiro_par(grupo):
for n in grupo:
if n % 2 == 0:
return n
return None
print(primeiro_par((3, 8, 12, 7)))
print(primeiro_par((3, 5, 7)))
r = primeiro_par((3, 5, 7))
if r is None:
print("nenhum par")A saída é 8, None e nenhum par. Se o laço achar um par, a função devolve na hora. Se o laço acabar sem achar, o programa chega ao return None final, que avisa "não achei". Quem chama testa com is None. Em vez de uma variável achou, o próprio valor devolvido diz o que aconteceu.
O recuo do return decide tudo. Dentro do laço, ele encerra na primeira volta:
def soma_ate(n):
total = 0
for i in range(1, n + 1):
total = total + i
return total
print(soma_ate(4))
def soma_ate2(n):
total = 0
for i in range(1, n + 1):
total = total + i
return total
print(soma_ate2(4))A saída é 1 e 10. A primeira versão tem o return recuado dentro do for, e a função termina na primeira volta, com total valendo 1. A segunda, com o return na coluna do for, só devolve depois que o laço acaba, e a soma de 1 a 4 sai certa, 10. Quando uma função com laço entrega o primeiro elemento em vez do total, olhe o recuo do return.
Sem return, a função devolve None
Quando a função termina sem passar por um return com valor, o Python entrega None, o valor que significa "nada". É o caso da função que só imprime, como a dobro_print. Duas variações sutis do mesmo problema:
def soma(a, b):
a + b
def soma2(a, b):
return
a + b
print(soma(2, 3))
print(soma2(2, 3))
x = print("oi")
print(x)A saída é None, None, oi e None. Na soma, a expressão a + b é calculada e jogada fora: sem return, ninguém a recebe, e o Python não avisa. Na soma2, o return está sozinho numa linha, o que entrega None e encerra, e o a + b abaixo é código morto. E o próprio print também devolve None, o que o último print(x) mostra.
O esquecimento mais traiçoeiro é o de um caminho só:
def classificar(n):
if n < 0:
return "negativo"
elif n > 0:
return "positivo"
print(classificar(5))
print(classificar(0))A saída é positivo e None. Para o 0, nenhuma condição serviu, e a função terminou sem devolver. A pergunta de conferência é a mesma do if: todos os caminhos da função terminam num return? Um return final, fora do if, cobre o resto.
Devolver vários valores
Uma função pode devolver mais de um valor, separando-os por vírgula. O que chega a quem chamou é uma tupla:
def dividir(a, b):
q = a // b
r = a % b
return q, r
resultado = dividir(7, 2)
print(resultado, type(resultado))
print(resultado[0], resultado[1])
q, r = dividir(7, 2)
print("quociente", q, "resto", r)
q2, r2 = dividir(17, 5)
print(q2, r2)
print(divmod(17, 5))A saída é (3, 1) <class 'tuple'>, 3 1, quociente 3 resto 1, 3 2 e (3, 2). O return q, r devolve um objeto só, a tupla (3, 1), que pode ser guardada inteira e lida por posição, resultado[0] e resultado[1], ou aberta em dois nomes de uma vez, q, r = dividir(7, 2). Essa abertura se chama desempacotamento. A função embutida divmod faz exatamente isso: devolve o quociente e o resto numa tupla.
O desempacotamento exige que os nomes e os valores tenham a mesma contagem. Com nomes demais, o Python reclama:
def dividir(a, b):
return a // b, a % b
q, r, s = dividir(7, 2)Traceback (most recent call last):
File "main.py", line 4, in <module>
ValueError: need more than 2 values to unpackO Python do computador diz ValueError: not enough values to unpack (expected 3, got 2), que traz as duas contagens. O sentido é o mesmo: três nomes para dois valores. Se sobrarem valores, o erro é too many values to unpack.
Outro engano é tratar a tupla como se fosse um número:
def dividir(a, b):
return a // b, a % b
q = dividir(7, 2)
print(q + 1)Traceback (most recent call last):
File "main.py", line 5, in <module>
TypeError: unsupported types for __add__: 'tuple', 'int'A variável q guarda (3, 1), e somar 1 a uma tupla não faz sentido. Quando uma função devolve mais de um valor, a pergunta é sempre a mesma: eu guardei a tupla inteira ou abri em nomes?
Uma função que calcula mais de uma estatística é um bom uso. As funções prontas min, max e sum, e o *valores do artigo anterior, ajudam:
def resumo(*valores):
menor = min(valores)
maior = max(valores)
media = sum(valores) / len(valores)
return menor, maior, media
mn, mx, md = resumo(7, 3, 9, 5)
print("menor", mn, "maior", mx, "media", md)
print(resumo(4, 8))A saída é menor 3 maior 9 media 6.0 e (4, 8, 6.0). A função devolve três valores, e quem chama escolhe como recebê-los. Os nomes mn e mx evitam sobrescrever min e max, as funções prontas.
Na ESP32
Em hardware, o return serve para transformar leituras em decisões. O botão com pull-up, por exemplo, devolve 0 quando apertado, e uma função pode traduzir isso numa pergunta direta:
from machine import Pin
botao = Pin(4, Pin.IN, Pin.PULL_UP)
estado = botao.value()
print("estado", estado)
def apertado(pino):
return pino.value() == 0
print(apertado(botao))
if apertado(botao):
print("apertado")
else:
print("solto")A saída é estado 1, False e solto. O botao.value() é uma chamada que devolve, e a função apertado esconde o detalhe de que apertar é o valor 0 (o motivo está no artigo sobre pull-up e pino flutuante). No simulador sem circuito, o pull-up mantém o pino em 1 e o botão aparece solto. O programa principal passa a ler if apertado(botao):, e se o botão for trocado por um sensor ativo em nível alto, só a função muda.
Conversões entre faixas são outro uso clássico. O ADC lê de 0 a 4095, o PWM aceita de 0 a 1023, e uma função de mapear com um limitar ao lado resolve os dois:
def mapear(x, de_min, de_max, para_min, para_max):
return (x - de_min) * (para_max - para_min) // (de_max - de_min) + para_min
print(mapear(2048, 0, 4095, 0, 100))
print(mapear(2048, 0, 4095, 0, 1023))
print(mapear(0, 0, 4095, 0, 1023))
print(mapear(4095, 0, 4095, 0, 1023))
def limitar(v, minimo, maximo):
if v < minimo:
return minimo
if v > maximo:
return maximo
return v
print(limitar(-20, 0, 1023))
print(limitar(500, 0, 1023))
print(limitar(2000, 0, 1023))A saída é 50, 511, 0, 1023, 0, 500 e 1023. A divisão // mantém tudo em inteiros, o que evita o float de 32 bits da ESP32 em contas simples (o artigo sobre ADC mostra as faixas e a atenuação). A limitar usa a escada de returns da seção anterior, sem else.
A leitura que pode falhar combina bem com o None. A função tenta e devolve o primeiro valor bom, ou None quando nada serviu, e quem chama decide o que fazer:
def tentar(leituras):
for v in leituras:
if v is not None:
return v
return None
print(tentar((None, None, 23.5)))
print(tentar((None, None)))A saída é 23.5 e None. Aqui a tupla faz o papel do sensor, como no artigo sobre break e continue. Num programa real, o laço chamaria o sensor a cada volta, e o None seria o sinal de "tente de novo" ou "desista".
Testar uma função
Uma função que devolve é fácil de testar: chame com um valor conhecido e compare com o resultado esperado.
def dobro(n):
return n * 2
assert dobro(2) == 4
print("passou")
print(dobro(2) == 4)
print(dobro(3) == 7)A saída é passou, True e False. O assert não imprime nada quando a condição é verdadeira, e interrompe o programa quando é falsa:
def dobro(n):
return n * 2
assert dobro(3) == 7, "dobro de 3 devia ser 6"Traceback (most recent call last):
File "main.py", line 4, in <module>
AssertionError: dobro de 3 devia ser 6O texto depois da vírgula é a mensagem do erro. Escrever dois ou três assert logo abaixo da função, antes de usá-la no programa, é um hábito que pega erros cedo. Com funções que só imprimem, esse tipo de teste não é possível, porque não há valor para comparar.
return fora de uma função
O return só faz sentido dentro de uma função. Escrito solto, no programa principal, o Python recusa:
return 5Traceback (most recent call last):
File "main.py", line 1
SyntaxError: 'return' outside functionO motivo costuma ser um recuo perdido: o return ficou na margem, fora do def.
Em sala de aula: onde o return costuma tropeçar
Estes casos se repetem nas turmas.
print no lugar de return
É o mais frequente. O exercício pede "uma função que devolva o dobro", e o aluno entrega uma que imprime. Na tela, o resultado parece certo. Quando o enunciado manda "mostrar o valor devolvido", a função continua imprimindo duas vezes ou entrega None ao print de fora. A conferência: a função tem a palavra return?
Chamar a função e não usar o resultado
O aluno escreve dobro(5) numa linha solta e espera ver 10. O valor foi devolvido e ninguém o recebeu. Em uma tela de terminal interativo, pode aparecer sem querer, mas num programa salvo, não. A solução é print(dobro(5)) ou x = dobro(5).
Dois return em sequência
def f(a, b):
return a
return bO aluno acha que a função devolve os dois. O segundo return nunca roda. Para devolver dois valores, é um return só, com vírgula.
return no recuo errado do laço
O caso da soma_ate que devolve 1. O sintoma é o resultado do primeiro elemento só. Olhe se o return está na coluna do for ou do corpo.
Esquecer um caminho
A função com if e elif sem else e sem return final. Nenhum erro, só um None que aparece em algum lugar distante. Teste com os valores de fronteira, como 0.
Desempacotar na contagem errada
q, r, s = dividir(7, 2). O aluno vê o ValueError e não entende por que "o computador pediu três". A contagem dos nomes à esquerda precisa ser igual à dos valores devolvidos.
Dar o nome de uma função embutida a uma variável
O min, max = resumo(...) funciona, mas apaga as funções min e max pelo resto do programa. O erro aparece longe dali, quando a próxima chamada a max(...) reclama que um número "não é chamável".
Exercício: resumo de leituras
Reescreva o resumo para uma lista de leituras de sensor: a função recebe quantas leituras vierem, descarta as que forem None e devolve a menor, a maior e a média. Se nenhuma leitura sobrar, devolve None. Comece com a versão sem None, que já está acima, e acrescente o filtro.
Uma dica para o filtro: percorra valores com um for, acumule as válidas numa soma e conte quantas foram, como no exemplo da média de ADC do artigo sobre break e continue. Um return None logo depois do laço cobre o caso sem leituras. Para melhorar, devolva também quantas leituras foram descartadas, o que dá uma tupla de quatro valores.
Perguntas frequentes
Qual a diferença entre print e return?
O print escreve na tela, e o valor que a função entrega a quem chamou continua sendo None. O return não escreve nada, e entrega o valor, que pode ser guardado, somado ou impresso por quem chamou.
Uma função pode ter mais de um return?
Pode, e é comum. Cada caminho do if pode ter o seu. Só o primeiro alcançado roda, porque o return encerra a função.
O que a função devolve se não tiver return?
None. O mesmo acontece quando o return não tem valor, ou quando o fluxo chega ao fim do corpo sem passar por nenhum.
Posso devolver uma lista, um texto ou um booleano?
Pode devolver qualquer valor. Textos, números, booleanos, tuplas e listas funcionam do mesmo jeito.
Preciso escrever return(x) com parênteses?
Não. O return é um comando, e não uma função. return x e return (x) fazem a mesma coisa, mas a primeira forma é a usual.
return a, b devolve uma lista?
Não, devolve uma tupla. A diferença é que a tupla não pode ser alterada depois, e para o desempacotamento isso não faz diferença.
Para continuar
Agora os desafios de funções ficam ao alcance, todos com return: Função Dobro e Função Triplo com um parâmetro, Área do Retângulo com dois, Função eh_par com booleano, Calculadora com Funções com duas funções e Maior de Dois com if. Se quiser rever a base, volte aos artigos sobre definir funções e sobre parâmetros e argumentos. A trilha Lógica com Python reúne todos.
O próximo artigo trata do escopo de variáveis: onde cada nome existe, por que o n de dentro da função não é o n de fora, quando se usa global e o que o nonlocal faz.