Funções em Python
return. Descubra quais variáveis uma função pode acessar e alterar, descreva suas funções com docstrings e divida um programa em funções pequenas e com nomes claros, que você constrói e testa uma de cada vez.BásicoAula 4 de 10 do curso Curso de Introdução à programação com Python
O que você vai aprender
- Escreva uma função com
def, execute-a por meio de uma chamada e acompanhe a ordem em que Python executa um programa que contém funções.- Defina uma função e chame-aEscreva o cabeçalho e o corpo indentado de uma função, escolha um nome claro e execute a função chamando-a com parênteses.
- Acompanhe o fluxo de execuçãoRastreie a ordem em que Python executa instruções quando funções chamam outras funções e preveja a saída de um programa com base nessa ordem.
- Defina uma função e chame-a
- Use parâmetros e argumentos para fornecer a uma função os valores com que ela trabalha, associados por posição, por nome ou por meio de valores padrão.
- Use parâmetros e argumentos posicionaisAdicione parâmetros ao cabeçalho de uma função, passe argumentos correspondentes em uma chamada e leia os erros produzidos por uma quantidade incorreta de argumentos.
- Chame funções com argumentos nomeadosPasse argumentos pelo nome do parâmetro, combine argumentos posicionais e nomeados na ordem correta e corrija os erros causados por combinações incorretas.
- Atribua valores padrão a parâmetrosTorne parâmetros opcionais com valores padrão, ordene corretamente os parâmetros obrigatórios e opcionais e saiba quando um valor padrão é criado.
- Use parâmetros e argumentos posicionais
- Use
returnpara devolver um valor ao código que chamou uma função, distinga retornar de imprimir e escreva funções cujos resultados possam ser armazenados, testados e combinados.- Retorne um valor e use-oTermine uma função com
return, use o valor retornado em variáveis e expressões e entenda por que retornar um valor é diferente de imprimi-lo. - Retorne por caminhos diferentes e combine resultadosEscreva funções com várias instruções return, retorne True ou False, retorne antecipadamente de um laço, retorne dois valores e passe o resultado de uma função para outra.
- Retorne um valor e use-o
- Preveja quais variáveis uma função pode acessar e alterar, passe dados para dentro e para fora por meio de parâmetros e valores de retorno e use
globalsomente quando for realmente necessário.- Trabalhe com variáveis locais e parâmetrosExplique por que variáveis criadas dentro de uma função existem apenas durante sua chamada, como Python encontra um nome e por que alterar um parâmetro não altera a variável do código chamador.
- Use variáveis globais com cuidadoLeia valores globais com segurança, entenda o erro causado ao atribuir um valor a um nome global, use a instrução
globalcorretamente e dê preferência a parâmetros e valores de retorno.
- Trabalhe com variáveis locais e parâmetros
- Descreva funções com docstrings, divida um problema em funções pequenas e com nomes claros e construa e verifique um programa uma função por vez.
- Documente funções com docstringsEscreva docstrings de uma linha e de várias linhas que sigam as convenções comuns e leia-as com
help(). - Divida um problema em funçõesDecomponha uma tarefa em etapas, transforme cada etapa em uma função com entradas e saídas claras e organize o programa em torno de uma função
main. - Construa e verifique um programa uma função por vezDesenvolva um programa em pequenas etapas, teste cada função com entradas cujos resultados você conhece e use tracebacks e impressões temporárias para encontrar defeitos dentro das funções.
- Documente funções com docstrings
Guia de estudo de Funções em Python
1Defina e chame suas próprias funções
Uma função dá nome a uma parte útil de código, para que você possa executá-la sempre que aquela tarefa for necessária. Escrever a definição e fazer uma chamada são ações distintas, e essa diferença explica por que alguns programas terminam sem mostrar nada. Você escreverá definições corretamente indentadas, escolherá nomes legíveis e acompanhará a execução quando uma função chama outra e depois retorna ao código chamador.
1.1 Defina uma função e chame-a
Uma função é um bloco de código com nome que realiza uma tarefa. Funções embutidas como print() e input() já oferecem tarefas úteis que você pode chamar; def permite criar suas próprias funções. Um bom nome transforma várias linhas de trabalho em uma chamada que indica o que você quer que seja feito.
Escreva o cabeçalho e o corpo
def greet():
print("Hello!")
print("Welcome to Python.")
greet()
greet()
O cabeçalho começa com def, seguido do nome, dos parênteses e de dois-pontos. As linhas indentadas formam o corpo. Use quatro espaços para cada nível de indentação. As linhas greet() sem indentação estão fora da função, portanto são chamadas no programa principal.
Quando Python chega à definição, ele cria a função e lhe dá o nome greet. Ele ainda não imprime nenhuma das mensagens. A primeira chamada começa na primeira linha do corpo e imprime “Hello!”, seguido de “Welcome to Python.”. A segunda chamada começa o corpo novamente e imprime as mesmas duas linhas. Há quatro linhas de saída ao todo.
Um nome e uma chamada são diferentes
Os parênteses em greet() fazem dela uma chamada, embora essa função não precise de entradas. Uma linha que contém apenas greet faz referência à função e não executa nada. print(greet) exibe uma descrição do objeto de função, incluindo um endereço de memória; ele não executa a saudação.
Python precisa ter executado uma definição antes que uma chamada use seu nome. Se um arquivo começa com greet() e define greet depois, a primeira linha gera NameError: name 'greet' is not defined. Coloque a definição acima da chamada no nível superior.
Escolha nomes que expliquem a tarefa
Use palavras em minúsculas unidas por sublinhados, como print_receipt ou convert_to_miles. Nomes podem conter letras, dígitos e sublinhados, mas não podem começar com um dígito nem ser uma palavra reservada como return. Os nomes distinguem maiúsculas de minúsculas: greet e Greet são nomes diferentes.
Mantenha os nomes embutidos disponíveis. Depois de input = "yes", o nome input se refere a texto, então input("Name? ") gera TypeError: 'str' object is not callable. Dar à variável o nome answer mantém a função embutida acessível.
Corrija primeiro a estrutura
A falta de dois-pontos no cabeçalho produz SyntaxError: expected ':'. Um corpo vazio ou sem indentação produz um IndentationError. Uma função planejada ainda precisa de uma instrução; pass é uma instrução provisória que não faz nada:
def print_receipt():
pass
print_receipt()
Esse programa é executado sem saída. A chamada chega a pass e depois ao fim do corpo. Substitua a instrução provisória pela tarefa real quando estiver pronto para implementá-la. Se uma linha deveria pertencer ao corpo, mas é executada no momento errado, verifique sua indentação antes de alterar a chamada.
Principais conclusões
- Use
def name():e um corpo indentado para definir uma função. - Uma definição cria a função; os parênteses fazem uma chamada que a executa.
- Execute a definição de uma função antes de fazer uma chamada que precise de seu nome.
- Escolha nomes descritivos em minúsculas com sublinhados e evite nomes embutidos.
- Use
passquando uma função planejada precisar de um corpo provisório válido.
1.2 Acompanhe o fluxo de execução
Um programa com funções não executa todos os corpos na ordem em que aparecem na página. Uma chamada altera o fluxo de execução: Python entra na função chamada, termina seu trabalho e retoma o código chamador logo após essa chamada.
Acompanhe uma chamada dentro de outra
def line():
print("----------")
def banner():
line()
print(" REPORT")
line()
print("Start")
banner()
print("End")
Primeiro, Python define line e banner. Nenhum dos corpos é executado. A próxima instrução imprime “Start”. A chamada a banner() entra em seu corpo, cuja primeira instrução chama line().
Python agora entra em line, imprime “----------” e chega ao fim. Ele retorna à próxima instrução em banner, que imprime “ REPORT”. A segunda chamada a line() imprime outra linha de traços. Por fim, banner termina, então o programa principal continua e imprime “End”.
A saída é:
Start
----------
REPORT
----------
End
Acompanhe as chamadas não concluídas
Enquanto line é executada, banner espera que ela termine. O programa principal também espera por banner. Python registra essas chamadas não concluídas na pilha de chamadas. A chamada ativa mais interna termina primeiro, e cada código chamador continua em sua própria próxima instrução.
Para um rastreamento no papel, numere as linhas do programa. Registre uma linha do corpo apenas quando a execução chegar a ela por meio de uma chamada. Em cada chamada, marque onde a execução será retomada. Escreva a saída quando seu print for executado, mantendo os espaços e as quebras de linha. Isso separa o caminho pelo código da saída que ele produz.
Defina funções auxiliares antes de serem necessárias
A definição da função auxiliar pode aparecer abaixo da definição da função que a chama:
def show_report():
draw_line()
print("Ready")
def draw_line():
print("====")
show_report()
Isso funciona porque ambas as definições foram executadas antes de a chamada final entrar em show_report. Python procura draw_line quando o corpo efetivamente a chama. Mover show_report() para cima de def draw_line(): faria a chamada falhar ao tentar usar a função auxiliar ausente.
Chamadas repetidas começam do início
Uma chamada dentro de um laço entra no corpo a cada repetição:
for i in range(3):
line()
Usando a primeira definição de line, isso imprime a linha de traços três vezes. A função começa na primeira instrução de seu corpo a cada chamada.
Se uma chamada falhar, Python mostra um traceback. Sua última linha apresenta o tipo de erro e a mensagem. As entradas de chamadas acima dela vão da chamada não concluída mais externa até a linha que falhou. Ler primeiro o erro final e depois verificar a linha mais interna e o código que a chamou ajuda a localizar tanto a operação que falhou quanto o caminho que forneceu seus dados.
Principais conclusões
- Rastreie as instruções dos corpos na ordem das chamadas, registrando a saída quando cada
printfor executado. - A pilha de chamadas acompanha as chamadas não concluídas e onde retomar a execução.
- Uma função auxiliar pode ser definida abaixo da função que a chama se sua definição for executada antes de sua chamada.
- Leia o erro final de um traceback e depois examine a linha que falhou e o código que a chamou.
2Passe informações para funções
Parâmetros permitem que uma função trate entradas diferentes sem reescrever seu corpo. O código chamador fornece argumentos, e Python associa esses valores aos nomes dos parâmetros antes de o corpo começar. Você associará argumentos por posição e por nome, combinará essas formas corretamente e escolherá valores padrão para casos comuns. Também verá por que um valor padrão é criado quando a definição é executada e como isso afeta uma lista usada como padrão.
2.1 Use parâmetros e argumentos posicionais
Uma função se torna reutilizável com entradas diferentes quando seu cabeçalho nomeia os valores de que ela precisa. Esses nomes são parâmetros. O código chamador fornece argumentos, que são os valores efetivamente usados em uma chamada específica.
Associe valores a nomes
def rectangle_area(width, height):
print("Area:", width * height)
rectangle_area(4, 2.5)
rectangle_area(3, 7)
Os parâmetros são width e height. Na primeira chamada, os argumentos são 4 e 2.5. Argumentos posicionais são associados da esquerda para a direita: width recebe 4 e height recebe 2,5. O corpo imprime “Area: 10.0”. A próxima chamada fornece novos valores aos mesmos nomes de parâmetros e imprime “Area: 21”.
Cada parâmetro funciona como uma variável dentro daquela chamada. Você não precisa atribuir valores a width e height antecipadamente; a chamada os fornece. Uma função sem parâmetros ainda precisa de parênteses vazios tanto na definição quanto nas chamadas.
A ordem pode mudar o significado
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet("cat", "Milo")
describe_pet("Milo", "cat")
A primeira chamada imprime “Milo is a cat”. A segunda imprime “cat is a Milo”. Ambas as chamadas são válidas em Python, então nenhum erro sinaliza a troca de significado. Leia a ordem do cabeçalho antes de escolher argumentos posicionais, especialmente quando vários parâmetros aceitam o mesmo tipo de valor.
Argumentos podem ser expressões
Python avalia cada expressão de argumento antes de o corpo começar. Com side = 6, a chamada rectangle_area(side, side) passa 6 duas vezes e imprime “Area: 36”. O nome da variável do código chamador não precisa corresponder a nenhum dos nomes dos parâmetros. A chamada rectangle_area(side + 1, 2) passa 7 e 2; ela não passa o texto “side + 1”.
Leia um erro de quantidade de argumentos
Todo parâmetro sem valor padrão precisa de um argumento. Com a função de área acima:
| Chamada | O que dá errado |
|---|---|
rectangle_area(4) | height está faltando. |
rectangle_area(4, 2, 1) | Foram fornecidos três argumentos para dois parâmetros. |
A primeira gera TypeError: rectangle_area() missing 1 required positional argument: 'height'. A segunda gera TypeError: rectangle_area() takes 2 positional arguments but 3 were given. Verifique o cabeçalho da função indicada e depois conte como a chamada preenche seus parâmetros.
Passe o tipo de valor necessário para a tarefa
Python não impõe um tipo simplesmente porque um parâmetro se chama width. rectangle_area("4", 2) imprime “Area: 44”, pois multiplicar um texto por um inteiro repete esse texto. Como input() retorna texto, converta a entrada numérica antes de passá-la:
width = float(input("Width: "))
rectangle_area(width, 2)
Aqui float() transforma o texto digitado em um número antes que a função de área o receba.
Principais conclusões
- Um parâmetro é um nome no cabeçalho; um argumento é um valor fornecido por uma chamada.
- Argumentos posicionais preenchem parâmetros da esquerda para a direita.
- Python avalia expressões de argumentos antes de executar o corpo da função.
- Todo parâmetro obrigatório precisa de um valor; argumentos ausentes ou extras geram
TypeError. - Converta a entrada numérica de texto antes de passá-la para cálculos.
2.2 Chame funções com argumentos nomeados
Um argumento nomeado identifica seu parâmetro de destino na chamada. Isso facilita a leitura quando vários valores podem ser confundidos. Python associa o nome ao do cabeçalho, em vez de usar sua posição.
Associe pelo nome
def describe_pet(animal, name):
print(name, "is a", animal)
describe_pet(name="Milo", animal="cat")
describe_pet(animal="cat", name="Milo")
Ambas as chamadas imprimem “Milo is a cat”. A ordem dos argumentos nomeados pode mudar porque cada valor identifica o parâmetro que preenche. A mesma ideia torna rectangle_area(width=4, height=2.5) compreensível sem verificar qual dimensão veio primeiro.
Um nome de argumento não é uma nova variável no código chamador. Em describe_pet(name="Milo", animal="cat"), name= direciona “Milo” ao parâmetro. Ele não atribui “Milo” a uma variável de nível superior chamada name. Escreva argumentos nomeados sem espaços em torno de =, seguindo o estilo usual do Python.
Combine argumentos posicionais e nomeados
describe_pet("cat", name="Milo")
O primeiro argumento preenche animal por posição. O argumento nomeado preenche name, então cada parâmetro recebe exatamente um valor. Argumentos posicionais devem vir primeiro. A chamada describe_pet(name="Milo", "cat") é rejeitada com SyntaxError: positional argument follows keyword argument.
Para examinar uma chamada mista, preencha as posições dos argumentos posicionais da esquerda para a direita e depois associe os argumentos nomeados. Verifique se nenhuma posição foi preenchida duas vezes e se nenhum parâmetro obrigatório ficou vazio.
Corrija argumentos nomeados duplicados ou desconhecidos
| Chamada | Diagnóstico |
|---|---|
describe_pet("cat", animal="dog") | animal recebe tanto “cat” quanto “dog”. |
describe_pet(animal="cat", nmae="Milo") | O cabeçalho não tem um parâmetro chamado nmae. |
A duplicação gera TypeError: describe_pet() got multiple values for argument 'animal'. O erro de digitação gera TypeError: describe_pet() got an unexpected keyword argument 'nmae'. Compare os nomes caractere por caractere; letras maiúsculas e minúsculas também importam. Mudar a ordem dos argumentos não corrige uma atribuição duplicada a um parâmetro.
Reconheça argumentos nomeados em funções embutidas
print("a", "b", "c", sep="-")
print("Loading", end="...")
print("done")
A primeira linha imprime “a-b-c”. sep fornece o texto entre os valores exibidos. As duas chamadas seguintes produzem “Loading...done” em uma linha: end substitui a habitual nova linha após “Loading”.
Algumas funções embutidas também aceitam argumentos nomeados; por exemplo, round(3.14159, ndigits=2) produz 3,14. Use os nomes de parâmetros documentados para a função que você está chamando. Uma palavra descritiva inventada por você não é reconhecida apenas porque parece adequada à tarefa.
Principais conclusões
- Argumentos nomeados são associados aos nomes dos parâmetros, então sua ordem pode variar.
- Coloque argumentos posicionais antes dos argumentos nomeados.
- Preencha cada parâmetro exatamente uma vez e escreva cada nome de argumento corretamente.
- Um nome de argumento em uma chamada direciona um valor; ele não atribui um valor a uma variável do código chamador.
- Em
print,sepcontrola os separadores eendcontrola o terminador.
2.3 Atribua valores padrão a parâmetros
Um valor padrão permite que uma chamada omita um argumento quando uma escolha comum é adequada. Escreva o valor padrão ao lado do parâmetro no cabeçalho. Fornecer um argumento substitui o valor padrão naquela chamada.
Torne um parâmetro opcional
def greet(name, greeting="Hello"):
print(greeting + ",", name + "!")
greet("Ana")
greet("Ana", "Welcome")
greet("Ana", greeting="Hi")
A saída é “Hello, Ana!”, “Welcome, Ana!” e “Hi, Ana!”. name é obrigatório porque não tem valor padrão. Portanto, greet() gera um TypeError, embora o outro parâmetro seja opcional.
Nesses cabeçalhos, parâmetros obrigatórios vêm antes dos parâmetros com valores padrão. def greet(greeting="Hello", name): é inválido. Python informa um erro de sintaxe sobre um parâmetro sem valor padrão que vem depois de um com valor padrão. Mova name para antes de greeting para mantê-lo obrigatório.
Altere uma opção
def order_coffee(size, shots=1, milk="none"):
print(size, "coffee,", shots, "shot(s), milk:", milk)
order_coffee("large", milk="oat")
Isso imprime “large coffee, 1 shot(s), milk: oat”. O argumento nomeado chega a milk enquanto shots mantém 1. Uma chamada posicional order_coffee("medium", 2) altera shots e deixa milk em “none”. A associação posicional não pula um parâmetro opcional para chegar ao próximo.
Funções embutidas também oferecem valores padrão: um print() comum separa valores com um espaço e termina com uma nova linha. round(3.7) produz o número inteiro 4; round(3.14159, 2) solicita duas casas decimais e produz 3,14.
Valores padrão são criados quando a definição é executada
rate = 0.05
def price_with_tax(price, tax_rate=rate):
return price * (1 + tax_rate)
rate = 0.08
print(price_with_tax(100))
print(price_with_tax(100, rate))
O valor padrão armazena o valor 0,05 quando def é executado. Alterar rate depois não altera esse valor padrão armazenado. As chamadas imprimem “105.0” e “108.0”: apenas a segunda fornece explicitamente a nova taxa.
Evite compartilhar uma lista por acidente
Uma lista contém itens, e append adiciona um item a essa mesma lista. Com uma lista como valor padrão, todas as chamadas que omitem o argumento a compartilham:
def add_item(item, basket=[]):
basket.append(item)
print(basket)
add_item("apple")
add_item("pear")
Isso imprime ['apple'] e depois ['apple', 'pear']. A lista padrão foi criada uma vez, não uma vez por chamada. Para criar uma lista nova para cada argumento omitido, use None como sinal:
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
print(basket)
Agora essas duas chamadas imprimem ['apple'] e ['pear']. Uma lista fornecida explicitamente continua sendo usada como foi passada. Descreva os parâmetros opcionais e seus valores padrão na docstring para que o código chamador saiba quais valores são escolhidos quando eles são omitidos.
Principais conclusões
- Um argumento opcional omitido usa seu valor padrão; um argumento explícito o substitui.
- Coloque parâmetros obrigatórios antes de parâmetros com valores padrão.
- Use um argumento nomeado para alterar uma opção posterior sem preencher os parâmetros opcionais anteriores.
- Expressões de valores padrão são avaliadas uma vez, quando
defé executado. - Uma lista mutável usada como valor padrão é compartilhada pelas chamadas que a omitem.
- Use
Nonee crie uma lista no corpo quando cada argumento omitido precisar de uma lista nova.
3Devolva resultados com valores de retorno
Um cálculo se torna mais útil quando seu resultado pode alimentar outro cálculo, uma condição ou uma exibição. A instrução return torna isso possível ao devolver um valor ao código chamador. Você distinguirá retornar de imprimir, rastreará o primeiro return executado e verificará caminhos que podem terminar sem um resultado útil. Depois, criará funções booleanas, concluirá buscas corretamente e combinará resultados de funções pequenas.
3.1 Retorne um valor e use-o
Uma função pode fornecer ao código chamador um resultado para usar. A instrução return encerra a chamada e devolve seu valor. No ponto da chamada, ela passa a representar o valor retornado.
Armazene e combine resultados
def rectangle_area(width, height):
return width * height
area = rectangle_area(4, 2.5)
print(area)
print(rectangle_area(3, 4) + rectangle_area(2, 5))
A primeira chamada retorna 10,0, que é atribuído a area; o primeiro print o exibe. Na última linha, as duas chamadas retornam 12 e 10. Python soma esses resultados e imprime “22”. A própria função não contém print, então pode fornecer tanto um resultado armazenado quanto parte de um cálculo maior.
Um valor retornado também pode ser testado em uma condição ou passado para outra função. Isso separa a tarefa de calcular da decisão do código chamador sobre como usar a resposta.
Imprimir e retornar têm tarefas diferentes
def double_print(n):
print(n * 2)
result = double_print(5)
print(result)
A chamada exibe “10”, mas esse número exibido não é devolvido como resultado. double_print chega ao fim de seu corpo, então retorna None. Portanto, a última linha imprime “None”.
| Operação | Para onde vai o valor |
|---|---|
print(value) | Exibe-o para uma pessoa. |
return value | Devolve-o ao código chamador para o programa usar. |
double_print(5) + 1 primeiro imprime “10” e depois gera TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'. Substitua o corpo por return n * 2 quando o código chamador precisar do número dobrado. Uma função destinada apenas a produzir um efeito, como exibir uma mensagem, pode retornar None; essas funções são às vezes chamadas de funções sem retorno útil. Uma função com um resultado retornado útil é às vezes chamada de função com retorno útil.
Pare no primeiro return executado
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print("Converted")
print(to_fahrenheit(20))
Isso imprime “68.0”. O print dentro do corpo nunca é alcançado porque return já encerrou a chamada. Remova essa instrução inalcançável ou mova uma ação necessária para antes do return. A conversão retorna números de ponto flutuante porque / produz um número desse tipo. As entradas 100 e -40 produzem 212,0 e -40,0.
Um return sem expressão também encerra uma chamada, retornando None. Toda chamada de função tem um resultado, mesmo quando nenhum valor útil foi fornecido.
Torne os resultados visíveis em um arquivo de programa
Um rectangle_area(3, 4) sozinho calcula 12 e depois descarta o resultado não utilizado em um arquivo. Use print(rectangle_area(3, 4)) para exibi-lo ou atribua-o a uma variável. O interpretador interativo exibe resultados de expressões, exceto None, então um teste bem-sucedido no interpretador pode parecer diferente da execução da mesma linha em um arquivo.
Principais conclusões
return valueencerra a chamada e faz com que ela represente esse valor.- Imprimir exibe um valor; retornar o disponibiliza ao código chamador.
- Chegar ao fim do corpo ou usar um
returnsem valor produzNone. - Instruções após um return executado não são executadas naquela chamada.
- Use um resultado retornado armazenando-o, imprimindo-o, testando-o ou combinando-o.
3.2 Retorne por caminhos diferentes e combine resultados
Entradas diferentes podem precisar de respostas diferentes. Uma função pode ter várias instruções return, mas uma chamada para na primeira que executa. Siga o caminho efetivo por seus ramos e laços para encontrar o resultado.
Ordene testes que se sobrepõem
def letter_grade(score):
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
return "F"
Para 85, o primeiro teste é falso e o segundo é verdadeiro. A função retorna “B” sem testar as condições restantes. Para 42, os três testes são falsos, então o return final fornece “F”. Instruções if separadas funcionam porque cada ramo que corresponde encerra a chamada.
O maior valor limiar deve ser verificado primeiro aqui. Se score >= 70 viesse primeiro, uma pontuação de 95 retornaria “C”. Com intervalos sobrepostos, uma correspondência ampla e antecipada pode ocultar uma resposta posterior mais específica.
Cubra o caminho sem ramo correspondente
def sign(n):
if n > 0:
return "positive"
elif n < 0:
return "negative"
return "zero"
A última linha trata o zero. Sem ela, sign(0) chegaria ao fim e retornaria None. Rastreie uma entrada de cada ramo e qualquer caso restante; testar apenas entradas positivas e negativas deixaria essa lacuna passar despercebida.
Retorne uma comparação booleana
def is_even(n):
return n % 2 == 0
if is_even(10):
print("Even")
A comparação já produz True ou False. is_even(10) retorna True, enquanto is_even(7) retorna False. Use o resultado diretamente em uma condição. Um == True adicional não ajuda no teste.
Termine uma busca antes de informar que não houve correspondência
def smallest_divisor(n):
for d in range(2, n):
if n % d == 0:
return d
return n
Para 91, os candidatos de 2 a 6 falham, então 7 o divide exatamente. Retornar 7 encerra tanto o laço quanto a função. Para 13, o laço não encontra nenhum divisor, então o return final fornece 13.
Um teste de primalidade precisa permitir que a busca continue após um candidato falhar:
def is_prime(n):
if n < 2:
return False
for d in range(2, n):
if n % d == 0:
return False
return True
O True final está fora do laço. Colocá-lo em um else dentro do laço faria a função retornar depois de verificar apenas o primeiro candidato: 9 seria aceito incorretamente porque não é divisível por 2. Com a função corrigida, 9 e 1 retornam False; 2, 7 e 97 retornam True. Para 2, o laço não tem candidatos e a execução chega ao True final.
Devolva dois valores
def share(total, people):
return total // people, total % people
each, left = share(17, 5)
print(each, left)
A chamada retorna uma tupla, um resultado agrupado que contém 3 e 2. A atribuição a desempacota em dois nomes, então a saída é “3 2”. Imprimir a chamada diretamente mostraria “(3, 2)”. O número de nomes deve corresponder ao número de valores desempacotados.
Combine chamadas de dentro para fora
def add(a, b):
return a + b
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print(to_fahrenheit(add(10, 15)))
add primeiro retorna 25. Esse valor se torna o argumento de to_fahrenheit, que retorna 77,0. Por fim, print exibe “77.0”. Cada chamada interna deve retornar o valor de que a próxima função precisa.
Principais conclusões
- O primeiro return executado encerra uma chamada, então ordene com cuidado os testes que se sobrepõem.
- Inclua um resultado útil para cada caminho de entrada que a função deve tratar.
- Uma função booleana pode retornar uma comparação diretamente.
- Dentro de um laço de busca, retorne um resultado encontrado; informe que não houve correspondência após todos os candidatos falharem.
- Valores retornados separados por vírgulas formam uma tupla que pode ser desempacotada.
- Em chamadas aninhadas, o resultado interno se torna o argumento da chamada externa.
4Entenda onde as variáveis existem: escopo local e global
Um nome dentro de uma função pode parecer idêntico a um nome fora dela, embora se refira a uma variável distinta. O escopo indica onde um nome pode ser usado, e a atribuição ajuda a determinar a qual nome Python se refere. Você acompanhará parâmetros e outras variáveis locais durante uma chamada, distinguirá reatribuição de alteração de uma lista compartilhada e lerá configurações globais. Também corrigirá um erro comum de escopo e tornará explícitos os valores que mudam nas chamadas.
4.1 Trabalhe com variáveis locais e parâmetros
Escopo descreve onde um nome pode ser usado. Parâmetros e nomes aos quais se atribuem valores dentro de uma função são locais à chamada dessa função. Um código chamador e uma função podem usar nomes semelhantes sem compartilhar as mesmas variáveis locais.
Mantenha nomes locais dentro de sua chamada
def make_greeting():
message = "Hi"
print(message)
make_greeting()
Isso imprime “Hi”. Adicionar print(message) após a chamada gera NameError: name 'message' is not defined: o nome local não está disponível ali. Para disponibilizar o valor ao código chamador, retorne-o e armazene-o:
def make_greeting():
return "Hi"
message = make_greeting()
print(message)
O message de nível superior é uma nova variável do código chamador que recebe o valor retornado. A função não torna seus próprios nomes locais visíveis fora dela.
Cada chamada recebe novas variáveis locais. Se um corpo define count = 0, soma 1 e o imprime, duas chamadas imprimem “1” e “1”. A segunda chamada não continua com a contagem da primeira. Funções diferentes também podem usar nomes locais como total de forma independente.
Acompanhe o sombreamento e a busca de nomes
x = 10
def show():
x = 5
print(x)
show()
print(x)
A saída é “5” e depois “10”. O x local sombreia o x global dentro de show; a atribuição não altera o valor de nível superior. Uma variável global pertence ao escopo de nível superior do arquivo. Atribuições comuns fora de funções criam variáveis globais.
Para uma função definida no nível superior do arquivo, Python procura um nome entre seus nomes locais, depois entre os globais do arquivo e então entre os nomes embutidos, como print. A primeira correspondência é usada. Portanto, nomes locais e globais são lugares diferentes a verificar quando um valor parece errado.
Reatribuir um parâmetro não altera o nome do código chamador
def add_bonus(points):
points = points + 10
print(points)
score = 50
add_bonus(score)
print(score)
points começa com o valor 50. Sua reatribuição local faz com que valha 60, então a primeira saída é “60”. O score do código chamador ainda é 50. Para atualizar esse nome explicitamente, use uma função que retorne points + 10 e depois escreva score = add_bonus(score).
Alterar uma lista é outra operação
Uma lista pode ser compartilhada por meio de dois nomes:
def add_guest(guests, name):
guests.append(name)
party = ["Ana"]
add_guest(party, "Ben")
print(party)
O parâmetro guests e a variável party do código chamador se referem à mesma lista. append altera o conteúdo dessa lista, então a saída é “['Ana', 'Ben']”. Atribuir guests = [] dentro da função faria apenas o nome local apontar para uma nova lista; party ainda se referiria à original. Ao rastrear uma lista passada como argumento, pergunte se a linha altera o objeto compartilhado ou apenas reatribui um nome local.
Principais conclusões
- Parâmetros e nomes aos quais se atribuem valores dentro de uma função são locais à sua chamada.
- Cada chamada recebe novas variáveis locais; valores de retorno levam resultados para fora.
- Um nome local pode sombrear um global sem alterar o valor global.
- Reatribuir um parâmetro deixa inalterada a variável do código chamador.
- Modificar uma lista compartilhada altera a lista vista pelo código chamador.
4.2 Use variáveis globais com cuidado
Uma função pode ler um nome global sem uma declaração. Atribuir um valor a um nome em seu corpo segue uma regra diferente, e confundir essas operações é uma causa comum de UnboundLocalError.
Leia uma configuração fixa
TAX_RATE = 0.25
def tax(amount):
return amount * TAX_RATE
print(tax(80))
A saída é “20.0”. amount é local; TAX_RATE é lida entre as variáveis globais do arquivo. Letras maiúsculas indicam uma constante por convenção, sinalizando que o programa deve manter a configuração fixa. Python não impõe essa convenção.
A atribuição torna um nome local em todo o corpo
total = 0
def add_to_total(amount):
total = total + amount
add_to_total(5)
A atribuição torna total local em toda add_to_total. Para calcular o lado direito, Python tenta ler esse nome local antes que ele tenha um valor. Ele não recorre ao total global. A chamada gera UnboundLocalError: cannot access local variable 'total' where it is not associated with a value.
A decisão se baseia no corpo inteiro, não apenas nas linhas já executadas. Um corpo com print(count) seguido de count = 10 também trata count como local na linha de impressão. Um count global não pode fornecer o valor local ausente.
Declare uma atribuição global intencional
total = 0
def add_to_total(amount):
global total
total = total + amount
add_to_total(5)
add_to_total(7)
print(total)
Agora tanto a leitura quanto a atribuição se referem ao nome global, então a saída é “12”. Coloque global total antes de qualquer uso de total na função. Usar o nome antes de sua declaração é um erro de sintaxe.
Uma declaração sozinha não cria um valor. Uma atribuição posterior pode criar uma variável global que não existia: o corpo de uma função que contém global level e depois level = 1 cria a variável global level quando chamado.
Mostre a alteração por meio de entradas e de um resultado
O mesmo total acumulado pode ser escrito com uma interface explícita:
def add_to_total(total, amount):
return total + amount
total = 0
total = add_to_total(total, 5)
total = add_to_total(total, 7)
print(total)
Isso também imprime “12”. Cada chamada mostra o valor antigo sendo passado, e a atribuição mostra para onde vai o novo valor. Você pode verificar add_to_total(10, 3) por conta própria sem configurar primeiro um estado global oculto. Várias funções alterando a mesma variável global fazem seu comportamento depender da ordem em que são executadas.
| Operação dentro de uma função | Precisa de declaração? |
|---|---|
| Ler uma configuração global | Não. |
| Reatribuir um nome global | global name antes do uso. |
| Acrescentar a uma lista global existente | Não; o nome não é reatribuído. |
Ler uma lista compartilhada e alterar seu conteúdo usa a referência existente. Substituir esse nome global por uma lista diferente é uma atribuição, então a regra de atribuição se aplica.
Principais conclusões
- Leia um nome global sem uma declaração especial.
- Uma atribuição em qualquer ponto de uma função torna esse nome local, a menos que seja declarado global.
- Ler uma variável local sem valor atribuído gera
UnboundLocalError. - Coloque
global nameantes de usar um nome que a função reatribui globalmente de forma intencional. - Prefira parâmetros e valores de retorno quando um valor que muda puder ser passado explicitamente.
- Modificar uma lista e reatribuir seu nome seguem regras diferentes.
5Documente e projete programas com funções
Boas funções precisam de tarefas claras e de código correto. Quem chama uma função deve poder saber do que ela precisa, o que retorna e que efeito produz sem estudar cada linha de seu corpo. Você escreverá docstrings, dividirá um programa completo em funções auxiliares e as conectará por meio de uma pequena função main. Depois, verificará uma parte por vez com resultados esperados, entradas nos limites e as pistas de um traceback.
5.1 Documente funções com docstrings
Quem chama uma função precisa conhecer sua tarefa sem ler toda a implementação. Uma docstring fornece essa descrição. Python reconhece uma string como a docstring da função quando ela é a primeira instrução do corpo.
Escreva primeiro uma descrição curta
def to_fahrenheit(celsius):
"""Convert a temperature from degrees Celsius to degrees Fahrenheit."""
return celsius * 9 / 5 + 32
print(to_fahrenheit.__doc__)
A saída é a frase dentro das aspas. Python armazena a docstring em __doc__; as aspas triplas não fazem parte da frase armazenada. help(to_fahrenheit) exibe a descrição junto com a assinatura to_fahrenheit(celsius). Passe o nome da função para help, sem chamá-la.
A convenção comum é usar três aspas duplas, mesmo para uma docstring de uma linha. Comece com um comando como “Retorne a área de um retângulo.” e termine com um ponto. Mantenha uma descrição curta e suas aspas de fechamento em uma linha. Você não precisa repetir o nome da função e a lista de parâmetros, pois a exibição de ajuda já os inclui.
Acrescente detalhes quando forem necessários para quem chama a função
def split_bill(total, people, tip_rate=0.2):
"""Return each person's share of a bill, including the tip.
total: the bill before the tip
people: the number of people sharing the bill
tip_rate: the tip as a fraction of the bill (default 0.2)
"""
return total * (1 + tip_rate) / people
A primeira linha informa o resultado. Uma linha em branco a separa dos detalhes sobre as entradas. O valor padrão é documentado como 0,2, uma fração da conta; isso evita que quem chama a função interprete 20 como o valor pretendido para uma gorjeta de 20 por cento. As aspas de fechamento de uma docstring de várias linhas ficam em uma linha própria.
Para split_bill(84, 4), a função aplica a gorjeta padrão e retorna 25,2. Quem chama a função pode entender o significado das três entradas antes de escolher os argumentos. Inclua unidades quando forem relevantes e descreva efeitos como a impressão, para que seja possível prever tanto o resultado quanto o comportamento visível.
Mantenha a documentação distinta dos comentários
| Forma | Finalidade principal |
|---|---|
| Primeira string no corpo | Descreve a função para quem a chama e aparece em help. |
Comentário com # no corpo | Explica um detalhe do código para quem lê a implementação. |
Uma string colocada depois de uma atribuição ou de outra instrução do corpo não é a docstring da função. Ela é uma expressão de string não utilizada, e __doc__ é None se não houver uma docstring como primeira instrução. Um comentário com # também não se torna a descrição de ajuda.
Escreva o resumo enquanto decide a tarefa da função. Se a frase precisar de várias ações sem relação entre si, reconsidere se a função deve ser dividida. Ao alterar parâmetros, valores padrão, valores retornados ou efeitos de impressão, atualize a docstring ao mesmo tempo; quem chama a função depende dela como parte da interface.
Principais conclusões
- A docstring de uma função é a primeira instrução de seu corpo.
- Use três aspas duplas e uma frase curta no imperativo terminada em ponto.
- Em descrições mais longas, separe o resumo dos detalhes com uma linha em branco.
- Descreva entradas relevantes, unidades, valores padrão, resultados e efeitos.
- Leia a documentação armazenada com
help(name)ouname.__doc__.
5.2 Divida um problema em funções
Decomposição significa dividir uma tarefa em tarefas menores. Cada função assume a responsabilidade por uma tarefa, com entradas claras e um resultado ou efeito claro. O programa principal pode então ser lido como uma curta sequência de etapas nomeadas.
Planeje os dados antes de escrever os corpos
Para um programa que informa a média de notas de provas e uma nota em letra, identifique três tipos de trabalho: ler notas, calcular uma média e escolher uma nota em letra. Decida o que cada função auxiliar recebe e retorna. Mantenha a exibição em main, onde os resultados são reunidos.
def get_score(prompt):
return float(input(prompt))
def average(a, b, c):
return (a + b + c) / 3
def letter_grade(score):
if score >= 90:
return "A"
if score >= 80:
return "B"
if score >= 70:
return "C"
return "F"
def main():
first = get_score("Test 1: ")
second = get_score("Test 2: ")
third = get_score("Test 3: ")
avg = average(first, second, third)
print("Average:", round(avg, 1), "Grade:", letter_grade(avg))
main()
Com as notas 78, 92 e 85, average retorna 85,0. Esse resultado se torna o argumento de letter_grade, que retorna “B”. A exibição é “Average: 85.0 Grade: B”.
main coordena a sequência; ela não precisa saber como letter_grade escolhe sua resposta. Usar uma função por meio de sua tarefa e interface, sem acompanhar cada instrução do corpo, é abstração procedural. Você já usa print dessa maneira.
Dê ao código chamador uma interface clara
A interface de uma função consiste em seu nome, parâmetros, resultado retornado e comportamento documentado. average(a, b, c) exige três números e retorna sua média. O código chamador não precisa ler uma solicitação de entrada nem capturar texto impresso para obter esse número. Você pode reescrever o cálculo mantendo as entradas e a saída combinadas, e as chamadas existentes continuam funcionando.
Use nomes como calculate_total e print_receipt para ações, e is_even ou has_discount para perguntas booleanas. Nomes de parâmetros como price e quantity explicam quais valores pertencem a cada posição. Nomes de uma letra podem ser adequados quando seu significado é claro, como nas três entradas de average.
Transforme repetição em parâmetros
Se várias partes de um programa imprimem títulos diferentes entre as mesmas linhas de sinais de igualdade, faça do título um parâmetro de print_heading(title). A estrutura repetida pertence a um único corpo, enquanto o texto variável pertence às chamadas. Uma alteração posterior no comprimento da linha exige apenas uma edição.
Escolha limites para as funções que tornem as tarefas mais fáceis de entender ou reutilizar. Colocar todas as instruções em uma main longa oculta as tarefas menores. Dividir cada expressão trivial em uma função auxiliar usada uma vez pode adicionar nomes sem melhorar a legibilidade. Um teste útil é verificar se uma frase curta consegue descrever cada tarefa e suas entradas e saídas.
Termine o arquivo com a chamada efetiva main() após todas as definições. Um programa que contém apenas definições criará suas funções e terminará sem executar seus corpos.
Principais conclusões
- Decomponha a tarefa em trabalhos com entradas e saídas nomeadas.
- Mantenha cálculos separados da entrada e da impressão quando precisarem ser reutilizados ou verificados.
- Faça
maincoordenar as funções auxiliares e chamemain()após as definições. - Use parâmetros para as partes que variam em código repetido.
- Uma interface estável permite que o código chamador use uma função sem depender de seu corpo.
- Escolha limites para as funções que tornem o programa mais fácil de entender.
5.3 Construa e verifique um programa uma função por vez
Criar várias funções antes de executar qualquer uma delas torna uma falha mais difícil de localizar. Desenvolvimento incremental significa escrever uma pequena parte, verificá-la e depois acrescentar a próxima. Você mantém um programa funcional enquanto reduz a quantidade de código novo a examinar.
Use uma função provisória durante o planejamento
Uma função provisória tem o cabeçalho pretendido e um corpo provisório. Uma docstring e pass mantêm a definição válida, mas a função retorna None até você implementá-la. Um retorno fixo pode ajudar a exercitar a exibição do código chamador sem afirmar que o cálculo real já funciona.
Comece com uma função auxiliar de cálculo cujo resultado você possa determinar independentemente. Quando ela se comportar corretamente, conecte-a à próxima função auxiliar. Deixe a entrada interativa para quando os cálculos puderem ser verificados com chamadas diretas.
Determine os resultados esperados antes de executar
Usando as funções average e letter_grade, as notas 70, 75 e 72 têm média de aproximadamente 72,33, então sua nota esperada é “C”. Verifique as duas etapas:
print(average(70, 75, 72))
print(letter_grade(average(70, 75, 72)) == "C")
As saídas são “72.33333333333333” e “True”. A comparação testa diretamente a nota esperada; observar apenas a própria saída de um programa sem uma expectativa independente pode deixar passar uma resposta errada, mas plausível.
Teste limites e entradas comuns
Para um valor limiar de 90, teste 90 e 89,9. A função de notas correta retorna “A” e “B”. Se sua primeira condição fosse score > 90, apenas a verificação do valor exato no limite revelaria que 90 passa incorretamente para o próximo teste.
Inclua um valor típico, limites exatos, valores próximos e entradas extremas que a função deve tratar. Para a função de notas, verificar 70 e 0 exercita o limite inferior de aprovação e o caminho final “F”. Uma verificação como print(letter_grade(85) == "B") é fácil porque a função recebe um valor e retorna seu resultado.
Leia o traceback e examine o valor recebido
Suponha que main chame letter_grade(input("Score: ")). Digitar “85” envia uma string para uma comparação com um número. O erro final é TypeError: '>=' not supported between instances of 'str' and 'int'. O traceback aponta para a comparação dentro da função auxiliar, enquanto uma linha anterior de chamada aponta para main.
A falha ocorre na comparação, mas a correção deve ser feita onde a entrada é preparada: converta-a com float() antes de passá-la. Um print("letter_grade got", score) temporário na primeira linha ajuda a revelar uma entrada inesperada. Se o tipo não estiver claro, examine o código chamador e a conversão que ele usa. Remova as impressões de depuração depois que o defeito for corrigido.
Relacione sintomas a causas prováveis
| Sintoma | Verifique |
|---|---|
Um resultado é None | Um return ausente ou um caminho não tratado. |
| Nenhum efeito aparece | Uma chamada ausente ou um resultado retornado não utilizado. |
| Um resultado plausível tem o significado errado | Argumentos trocados. |
NameError | Um nome de função ou variável escrito incorretamente ou indisponível. |
Depois de corrigir uma função auxiliar, execute novamente as verificações que exercitam os caminhos afetados e o código chamador que a conecta ao programa.
Principais conclusões
- Construa e verifique uma função antes de acrescentar a próxima.
- Calcule os resultados esperados de forma independente antes de compará-los com os resultados das chamadas.
- Teste limites exatos e valores próximos para detectar erros de comparação.
- Use o traceback para encontrar a falha e as chamadas que levaram a ela.
- Remova as impressões temporárias de depuração quando o problema for corrigido.
Exercícios resolvidos de Funções em Python
1Escreva uma função e rastreie suas chamadas
10 passos
- 1IntroduçãoDê um nome a uma tarefa
Uma função permite escrever uma tarefa útil uma vez e escolher quando executá-la. Você começará com uma saudação e depois rastreará um relatório que chama uma função auxiliar.
Mantenha duas perguntas separadas enquanto lê: “Python já criou essa função?” e “O programa já a chamou?”. A primeira torna o nome disponível; a segunda inicia o trabalho do corpo. Essa distinção explica por que um arquivo cheio de definições pode terminar sem saída.
- 2ExplicaçãoEscreva o corpo reutilizável
def greet(): print("Hello!") print("Welcome to Python.")O cabeçalho usa
def, um nome, parênteses e dois-pontos. As duas linhas indentadas por quatro espaços formam o corpo. Python cria a função quando essa definição é executada, mas nenhum dos prints é executado ainda.A próxima instrução sem indentação ficará fora da função. A indentação informa a Python onde essa tarefa termina; ela faz parte da estrutura do programa.
- 3ExemploExecute-a duas vezes
Adicione estas linhas após a definição:
greet() greet()A primeira chamada entra no corpo e imprime “Hello!”, seguido de “Welcome to Python.”. A segunda chamada começa novamente na primeira linha do corpo e imprime ambas as mensagens outra vez. Há quatro linhas de saída.
Os parênteses vazios ainda importam:
greetsozinho faz referência ao objeto de função. Ele não a chama, eprint(greet)exibe uma descrição da função em vez da saudação. - 4DesafioPreveja o efeito de uma chamada ausente
O que este arquivo exibe?
def ready(): print("Ready") ready print("Waiting")---reveal---
Ele exibe apenas “Waiting”. A definição cria
ready, e o nome sozinho faz referência a essa função sem executá-la. Para exibir a mensagem também, alterereadyparaready(). A chamada seria então executada antes do print final, produzindo “Ready” e “Waiting” em linhas separadas. - 5DicaMantenha nomes e corpos utilizáveis
Use nomes como
print_receipt: palavras em minúsculas unidas por sublinhados que descrevem a tarefa. Evite substituir um nome embutido. Atribuir texto ainputoculta a função, então uminput(...)posterior tenta chamar texto e falha.Um corpo inacabado precisa de uma instrução. Use um
passindentado como instrução provisória. Um comentário sozinho não constitui um corpo, e umpasssem indentação ficaria fora da função. - 6ExemploEntre no código chamador
def line(): print("----------") def banner(): line() print(" REPORT") line() print("Start") banner() print("End")Primeiro, ambas as definições são executadas sem imprimir. A instrução de nível superior imprime “Start”, depois
banner()entra no corpo de banner. Sua primeira linha chamaline, então banner deve esperar enquanto essa função auxiliar imprime seus traços. Não avance para o título até que a função auxiliar termine. - 7ExplicaçãoRetome um nível por vez
Quando
linetermina, a execução é retomada no print do título dentro debanner. Em seguida, banner chamalineuma segunda vez, produzindo a segunda linha de traços. Quando banner termina, o programa principal continua e imprime “End”.A pilha de chamadas do Python registra as chamadas não concluídas e seus pontos de retorno. Enquanto a função auxiliar é executada, banner e o programa principal estão esperando. Um rastreamento no papel pode marcar esses pontos de retorno e registrar a saída quando cada print for efetivamente executado.
- 8DesafioRastreie outra chamada de função auxiliar
Qual é a ordem da saída?
def inner(): print("I") def outer(): print("O") inner() print("P") outer() print("Q")---reveal---
As linhas são “O”, “I”, “P” e “Q”. O corpo externo imprime primeiro, faz uma pausa para
innere depois continua em seu próximo print. Somente apósouterterminar a instrução final de nível superior é executada. A ordem das definições, por si só, não determina a ordem da saída. - 9DesafioMova uma definição com segurança
Um arquivo define
showcom um corpo que chamaborder. Em seguida, definebordere termina com um laço que chamashow()duas vezes. A definição da função auxiliar mais abaixo causará um erro e quantas vezesborderserá executada?---reveal---
O programa funciona: ambas as definições foram executadas antes de o laço chamar
show. Cada chamada entra emshowpela primeira linha do corpo e chega a uma chamada deborder, então a função auxiliar é executada duas vezes. Mover o laço para cima da definição da função auxiliar deixaria seu nome indisponível quando fosse necessário pela primeira vez. - 10RecapitulaçãoLeia a partir da primeira instrução ativa
Ao rastrear um programa com funções:
- Verifique o cabeçalho e a indentação para localizar cada corpo.
- Comece pelas instruções de nível superior e entre em um corpo apenas por meio de uma chamada.
- Marque a próxima instrução do código chamador antes de acompanhar uma função auxiliar.
- Registre a saída quando seu print for executado.
Se uma chamada falhar, leia o erro final do traceback e depois examine a linha do corpo que falhou e o código chamador que levou até ela. O caminho das chamadas costuma ser a chave para entender o erro.
2Preencha as posições dos parâmetros
13 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoReutilize uma tarefa com valores diferentes
- 2ExemploAssocie a primeira e a segunda entrada
- 3ExplicaçãoAvalie os argumentos antes do corpo
- 4DesafioVerifique a quantidade de argumentos
- 5ExplicaçãoUse nomes para mostrar os papéis
- 6DesafioCorrija uma posição preenchida duas vezes
- 7DicaLeia opções nomeadas de funções embutidas
- 8ExemploTorne opcional a escolha comum
- 9DesafioPule uma opção usando o nome
- 10Ideia-chaveUm valor padrão guarda o valor do momento de sua criação
- 11ExemploVeja por que uma lista usada como valor padrão mantém itens
- 12DesafioCombine valores padrão com entradas nomeadas
- 13RecapitulaçãoCompare o cabeçalho com a chamada
3Acompanhe os valores de volta ao código chamador
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoObserve o que o código chamador recebe
- 2ExemploSubstitua a chamada por seu resultado
- 3ExplicaçãoSepare a tela do resultado
- 4DesafioEncontre o valor usado na soma
- 5DicaVerifique onde a chamada está sendo executada
- 6ExemploPare na primeira nota correspondente
- 7DesafioCubra a entrada entre os ramos
- 8Ideia-chaveDeixe uma comparação responder à pergunta
- 9ExemploRetorne um divisor encontrado
- 10DesafioCorrija um resultado de sucesso antecipado
- 11ExemploDesempacote um resultado agrupado
- 12ExemploPasse um resultado interno para fora
- 13DesafioCombine um caminho antecipado com um resultado
- 14RecapitulaçãoRastreie caminhos e valores retornados juntos
4Acompanhe nomes e objetos compartilhados
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoPergunte a que lugar o nome pertence
- 2ExemploDê a cada chamada seu próprio contador
- 3ExplicaçãoMantenha separados os nomes sujeitos a sombreamento
- 4DesafioMantenha explícita a atualização no código chamador
- 5ExemploAcompanhe uma lista compartilhada por um parâmetro
- 6ExemploLeia uma variável global sem declaração
- 7Ideia-chaveA atribuição determina antecipadamente o escopo local
- 8DesafioEscolha o escopo de uma atualização
- 9ConexãoPasse o valor que muda pela chamada
- 10DesafioSepare mutação de reatribuição
- 11RecapitulaçãoIdentifique a operação antes de prever seu efeito
5Projete e verifique um relatório de notas
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoConstrua um programa a partir de tarefas claras
- 2ExemploColoque a descrição onde help possa encontrá-la
- 3ExplicaçãoAcrescente detalhes que afetam uma chamada
- 4DesafioEncontre a documentação ausente
- 5ExplicaçãoEscolha uma tarefa para cada função auxiliar
- 6ExemploConecte as funções auxiliares em main
- 7DesafioSepare o cálculo da exibição
- 8DicaMantenha um programa funcional enquanto constrói
- 9ExemploVerifique um limite que pode revelar um defeito
- 10DesafioEncontre onde um tipo incorreto entra
- 11DesafioMantenha a documentação e uma verificação em acordo
- 12RecapitulaçãoUse a interface para orientar as verificações
Questões de Funções em Python
Conjunto 1: Rastreie entradas, escopo e resultados ausentes10 Questões de Prática
Questão 1 de 10
O que acontece quando inspect() é chamada?
count = 11
def inspect():
print(count)
count = 2
inspect()
Mostrar respostaOcultar resposta
count o torna local em todo o corpo, incluindo o print anterior. Essa variável local não tem valor quando o print tenta lê-la, então a chamada gera UnboundLocalError. Python não usa primeiro o 11 global para mudar ao escopo local apenas ao chegar à atribuição.Questão 2 de 10
O que show.__doc__ contém?
def show():
value = 2
"""Display the current value."""
print(value)
Mostrar respostaOcultar resposta
show.__doc__ é None. Aspas triplas sozinhas não bastam; mova a descrição para cima da atribuição para armazená-la como documentação.Questão 3 de 10
Como este corpo de função inacabado deve ser completado para que o arquivo seja válido, mas a função ainda não faça nada?
def print_ticket():
# Work to be added later
Mostrar respostaOcultar resposta
pass indentado é uma instrução de corpo válida que não faz nada. Comentários sozinhos não contam como o corpo obrigatório, então adicionar outro comentário ainda deixa a definição incompleta. Uma instrução sem indentação pertence ao exterior da função e não pode fornecer seu corpo ausente.Questão 4 de 10
O que este programa imprime?
def show_scaled(value, factor):
print(value * factor)
entry = "6"
show_scaled(entry, 3)
Mostrar respostaOcultar resposta
entry contém texto, e Python repete esse texto quando ele é multiplicado pelo inteiro 3. A saída é “666”, sem espaços inseridos. Para obter 18, seria necessário converter o texto em número antes da multiplicação; o nome do parâmetro não faz essa conversão.Questão 5 de 10
Qual valor é retornado?
step = 4
def advance(position, amount=step):
return position + amount
step = 9
result = advance(10)
Mostrar respostaOcultar resposta
def é executado, enquanto step vale 4. Portanto, omitir amount soma 4 a 10 e retorna 14. Alterar step para 9 depois não atualiza o valor padrão armazenado; para obter 19, seria necessário passar o novo valor explicitamente.Questão 6 de 10
Qual única alteração faz result conter 16 sem exibi-lo dentro da função auxiliar?
def square(n):
print(n * n)
result = square(4)
Mostrar respostaOcultar resposta
n * n envia 16 diretamente para a atribuição sem imprimir dentro da função auxiliar. return print(n * n) ainda imprime e retorna o resultado de print, que é None. Um return sem valor após um print também produz None, portanto não fornece o número calculado.Questão 7 de 10
O que é impresso?
def pack(total, size):
return total // size, total % size
def double(n):
return n * 2
boxes, spare = pack(29, 6)
print(double(boxes) + spare)
Mostrar respostaOcultar resposta
(4, 5), então boxes passa a valer 4 e spare passa a valer 5. Dobrar a quantidade de caixas produz 8 e, ao somar 5, imprime-se “13”. Obter 14 troca os dois valores desempacotados antes de dobrar, o que não segue a ordem do retorno.Questão 8 de 10
O que é impresso após as duas chamadas?
def add_guest(guests):
guests.append("Sol")
def replace_guests(guests):
guests = ["Tao"]
party = ["Ren"]
add_guest(party)
replace_guests(party)
print(party)
Mostrar respostaOcultar resposta
add_guest acrescenta “Sol” à mesma lista à qual party se refere. replace_guests apenas reatribui seu parâmetro local a uma nova lista, então party ainda se refere a ['Ren', 'Sol']. Esperar ['Tao'] confunde o redirecionamento do nome local com a substituição da referência do código chamador.Questão 9 de 10
Mostrar respostaOcultar resposta
main apenas muda a repetição de lugar e ainda exige várias edições para alterar esse comportamento compartilhado.Questão 10 de 10
> 50 escrito por engano?Mostrar respostaOcultar resposta
Conjunto 2: Leia chamadas e acompanhe seus resultados10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Que saída este programa produz?
def announce():
print("Open")
print("Ready")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Qual é a ordem da saída?
def mark():
print("M")
def stage():
print("S")
mark()
print("T")
print("R")
stage()
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
O que esta chamada imprime?
def describe_trip(origin, destination):
print(origin, "to", destination)
describe_trip("Mesa", "Salem")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Como você pode chamar esta função usando “Inez” para a pessoa e “West” para a sala?
def show_booking(person, room):
print(person, room)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
O que é exibido?
def label(text, copies=2):
print(text * copies)
label("Go")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
O que a última linha imprime?
def triple(value):
print(value * 3)
answer = triple(4)
print(answer)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O que esta função retorna para first_factor(25)?
def first_factor(n):
for candidate in range(2, n):
if n % candidate == 0:
return candidate
return n
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Quais são as duas linhas de saída?
level = 7
def show_level():
level = 3
print(level)
show_level()
print(level)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Qual é o papel da primeira string nesta função?
def square(n):
"""Return the square of n."""
return n * n
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Diagnostique chamadas e corrija o comportamento do programa10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Por que este programa funciona mesmo que tick seja definida abaixo de report?
def report():
tick()
def tick():
print("Done")
report()
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Qual valor de argumento chega a width?
def show_width(width):
print(width)
base = 8
show_width(base + 3)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Por que esta chamada falha?
def mark_pages(first, last):
print(first, last)
mark_pages(4, first=9)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Quais são as duas listas impressas?
def collect(value, bucket=[]):
bucket.append(value)
return bucket
print(collect("red"))
print(collect("blue", []))
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Qual é a saída completa?
def shift(n):
return n + 2
print("shifted")
shift(5)
print("done")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Uma função deve retornar True exatamente quando um inteiro é primo. Por que este corpo aceita 35 incorretamente?
def is_prime(n):
if n < 2:
return False
for d in range(2, n):
if n % d == 0:
return False
else:
return True
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O que é impresso?
total = 2
def add(amount):
global total
total = total + amount
return total
first = add(4)
second = add(first)
print(total, second)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
if score >= 60: depois que o código chamador passa input("Score: "). Qual correção trata o tipo da entrada?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Combine regras de funções em novas situações10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
O que é impresso?
def outer():
inner()
print("Y")
outer()
def inner():
print("X")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Qual é a saída completa, incluindo as quebras de linha?
print("N", "S", sep="/", end="|")
print("E", "W", sep="-")
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Uma nova chamada que omite items deve começar com uma lista nova, mas uma lista fornecida deve receber o acréscimo no próprio objeto. Qual corpo de substituição está correto?
def add_code(code, items=None):
# replacement body
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Qual alteração permite que esta função retorne o primeiro candidato correspondente ou None somente depois que todos os candidatos falharem?
def find_divisor(n):
for d in range(3, n):
if n % d == 0:
return d
else:
return None
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
O que a última linha imprime?
def change(values):
values.append("B")
values = ["C"]
values.append("D")
return values
original = ["A"]
result = change(original)
print(original, result)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Como o código chamador pode atualizar stock explicitamente sem que a função auxiliar altere uma variável global?
stock = 18
def remove(stock, amount):
return stock - amount
# caller statement
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
pass. O código chamador soma o resultado da função auxiliar a 7 e recebe TypeError. O que deve ser implementado em seguida?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
O que é impresso?
def add_fee(amount):
return amount + 3
def twice(amount):
return amount * 2
print(twice(add_fee(5)))
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
O que é impresso?
rate = 2
def scale(value, factor=rate):
return value * factor
def reset():
global rate
rate = 5
reset()
print(scale(3), scale(3, rate))
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Abstração procedural
letter_grade(avg) sem acompanhar cada comparação de valores limiares no corpo.Argumento
area(side + 1, 2), Python calcula o primeiro argumento antes de iniciar o corpo de area.Argumento nomeado
describe_pet(name="Milo", animal="cat") preenche os parâmetros em uma ordem fácil de ler.Argumento posicional
describe_pet(animal, name), describe_pet("cat", "Milo") coloca “cat” em animal.C
Cabeçalho
def, o nome da função, os parênteses dos parâmetros e dois-pontos.def print_line(length):, o cabeçalho nomeia a tarefa e sua entrada antes de o corpo começar.Caminho de retorno
Chamada aninhada
print(to_fahrenheit(add(10, 15))), a soma é executada antes da conversão e depois ocorre a impressão.Chamada de função
greet() executa a saudação, enquanto uma linha que contém apenas greet não a executa.Código chamador
banner() chama line(), o corpo de banner é o código chamador da função que desenha a linha.Constante
TAX_RATE = 0.25 para calcular imposto sem declarar esse nome global.Corpo da função
print indentadas abaixo de def greet(): pertencem ao corpo da função.D
Decomposição
Definição de função
def com cabeçalho e corpo indentado que cria uma função sob um nome.greet em def greet(): e espera uma chamada antes de executar seu corpo.Desempacotamento
share(17, 5) retorna 17 // 5, 17 % 5, a atribuição each, left = share(17, 5) coloca 3 em each e 2 em left.Desenvolvimento incremental
Docstring de uma linha
Docstring de várias linhas
tip_rate=0.2 é uma fração da conta, não 20.E
end
end de print controla o texto acrescentado após seus valores exibidos, usando uma nova linha por padrão.end="..." permite que o próximo print continue após os pontos em vez de começar uma nova linha.Escopo
make_greeting() fica indisponível para um print de nível superior após a chamada.Estado oculto
F
Fluxo de execução
banner(), concluir suas chamadas de funções auxiliares e depois imprimir “End”.Função
print_receipt() sempre que precisar exibir outro recibo.Função booleana
True ou False, muitas vezes diretamente de uma comparação.return n % 2 == 0 permite que is_even(n) seja usada diretamente como condição de um if.Função com retorno útil
Função provisória
pass criam uma função provisória válida, embora suas chamadas ainda retornem None até ela ser implementada.Função sem retorno útil
None.None.H
help
help exibe informações sobre uma função, incluindo sua assinatura e docstring armazenada, quando presente.help(to_fahrenheit) para examinar o conversor sem primeiro fornecer uma temperatura a ele.I
Impressão de depuração
Instrução global
global faz um nome dentro de uma função se referir à associação no nível do arquivo para leituras e atribuições posteriores.global total antes de a função usar total para atualizar uma contagem acumulada compartilhada.Instrução pass
pass é uma instrução provisória que não realiza nenhuma ação, permitindo que o corpo de uma função planejada seja válido em Python.pass pode ser chamada enquanto seu comportamento real de impressão ainda está sendo escrito.Instrução return
None.return width * height permite que o código chamador armazene uma área ou a use em outro cálculo.Interface
M
main
main coordena as tarefas menores de um programa, conectando entradas, resultados das funções auxiliares e a exibição final.main() executa as etapas de um relatório de notas após todas as definições das funções auxiliares terem sido executadas.Mutação
N
None
None é o valor especial do Python para ausência de valor, também útil como sinal de que uma entrada opcional foi omitida.basket=None, a função pode criar uma lista nova dentro de if basket is None:.P
Parâmetro
def area(width, height): dá a cada chamada de area nomes locais para suas duas dimensões.Parâmetro obrigatório
def greet(name, greeting="Hello"):, omitir name causa um erro de argumento ausente.Parâmetro opcional
milk="oat" enquanto deixa um parâmetro opcional anterior de quantidade de doses em seu valor padrão.Passagem mista de argumentos
describe_pet("cat", name="Milo"), a primeira posição é preenchida por posição e a segunda por nome.Pilha de chamadas
R
Rastreamento de exceção
Reatribuição
points = points + 10 altera o parâmetro local, deixando a pontuação do código chamador inalterada.Resultado esperado
Retorno antecipado
S
sep
sep de print controla o texto inserido entre os valores exibidos, usando um espaço por padrão.print("a", "b", "c", sep="-") exibe as três letras como “a-b-c”.Sombreamento
x = 5 local enquanto x = 10 é global, o x da função auxiliar produz 5 e um x global posterior ainda produz 10.String de documentação
T
Teste de limite
> em vez de >= por engano.Tupla
return total // people, total % people agrupa uma parcela e um resto.TypeError
TypeError informa uma operação inadequada sobre um valor ou uma chamada com uma combinação inválida de argumentos.TypeError pela entrada ausente.U
UnboundLocalError
UnboundLocalError ocorre quando uma função tenta ler um nome local antes que esse nome local tenha um valor.count torna local também um print(count) anterior, mesmo que exista uma variável global.V
Valor de retorno
area = rectangle_area(4, 2.5), area contém o resultado retornado 10,0 para uso posterior.Valor padrão
def greet(name, greeting="Hello"):, uma chamada pode omitir a saudação e ainda fornecer o nome.Valor padrão mutável
Variável global
x = 10 no nível superior permanece 10 quando uma função auxiliar atribui seu próprio x = 5 local separado.Variável local
count = 0, então duas chamadas podem imprimir o valor 1 independentemente.Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.