CSE 111: Programação com Funções

S02 - Atividade de Aprendizagem (1 de 2): Escrevendo Funções

Programas grandes costumam ser divididos em partes menores para facilitar a escrita e a depuração. Isso torna mais fácil escrevê-los, depurá-los e compreendê-los. Um programador pode dividir um programa Python em módulos, classes e funções. Nesta aula, você aprenderá a chamar funções existentes e, na próxima, aprenderá a escrever suas próprias funções.

Vídeos

Assista aos três vídeos a seguir sobre como escrever funções:

Conceitos

Aqui estão os conceitos e assuntos de programação em Python que você deve aprender durante esta aula.

O que é uma Função?

Uma função é um grupo de instruções que juntas executam uma tarefa. De forma geral, existem quatro tipos de funções em Python:

  1. Funções embutidas
  2. Funções da biblioteca padrão
  3. Funções de terceiros
  4. Funções definidas pelo usuário

Na aula anterior, você aprendeu a chamar os dois primeiros tipos de funções. Na semana 3, você aprenderá a instalar módulos de terceiros e chamar funções de terceiros. Nesta aula, você aprenderá a escrever e chamar funções definidas pelo usuário.

O que é uma Função Definida pelo Usuário?

É uma função criada por um programador. Aqui, o termo "usuário" se refere a quem programa, não a quem usa o software. Escrever funções definidas pelo usuário traz várias vantagens, incluindo:

  1. tornar seu código mais reutilizável
  2. tornar seu código mais fácil de entender e depurar
  3. tornar seu código mais fácil de alterar e adicionar recursos

Como Escrever uma Função Definida pelo Usuário

Para escrever uma função definida pelo usuário em Python, basta digitar o código que corresponde a este modelo:

def nome_da_funcao(param1, param2, …
  paramN):
  """string de documentação"""
  instrucao1
  instrucao2instrucaoN
  return valor

A primeira linha de uma função é chamada de cabeçalho ou assinatura e inclui o seguinte:

  1. a palavra-chave def (que é uma abreviação de "define", em inglês, ou definir)
  2. o nome da função
  3. a lista de parâmetros (com os parâmetros separados por vírgulas)

Aqui está o cabeçalho de uma função chamada desenhar_circulo, que recebe três parâmetros chamados x, y e raio:

def desenhar_circulo(x, y, raio):

Você poderia ler a linha de código anterior como: "Defina uma função chamada desenhar_circulo que receba três parâmetros chamados x, y e raio".

O nome da função deve começar com uma letra ou um sublinhado (_). O restante do nome deve ser composto por letras, dígitos (0–9) ou sublinhado. Um nome de função não pode incluir espaços ou outra pontuação. Ele deve ser significativo e descrever brevemente o que a função faz. Funções bem nomeadas geralmente começam com um verbo.

As instruções dentro de uma função são chamadas de corpo da função. Assim como outras instruções de bloco em Python, como if, else, while e for, que terminam com dois-pontos (:), o corpo de uma função também exige recuo (indentação). O corpo deve começar com uma string de documentação, ou seja, uma string entre aspas triplas que descreve a finalidade da função, seus parâmetros e o valor de retorno. O corpo de uma função pode conter quantas instruções forem necessárias, mas é recomendável limitar o tamanho das funções a menos de 20 linhas de código.

Diagrama de um cilindro circular reto com raio r e altura h
Um cilindro circular reto com raio r e altura h

O exemplo 1 contém uma função sem parâmetros chamada exibir_volume_do_cilindro(). Ela obtém dois números do usuário — raio e altura —, usa esses valores para calcular o volume de um cilindro circular reto e, em seguida, exibe o volume para o usuário.

# Exemplo 1
import math
# Define uma função chamada exibir_volume_do_cilindro.
def exibir_volume_do_cilindro():
  """Calcula e exibe o volume de um cilindro.
  Parâmetros: nenhum
  Retorna: nada
  """
  # Solicita o raio e a altura ao usuário.
  raio = float(input("Digite o raio de um cilindro: "))
  altura = float(input("Digite a altura de um cilindro: "))
  # Calcula o volume do cilindro.
  volume = math.pi * raio**2 * altura
  # exibe o volume do cilindro.
  print(f"Volume: {volume:.2f}")

Como a função exibir_volume_do_cilindro no exemplo 1 não aceita  parâmetros, ela deve ser chamada sem nenhum argumento, desta forma:

exibir_volume_do_cilindro()

Como Tornar uma Função Definida pelo Usuário Reutilizável

Como a função exibir_volume_do_cilindro no exemplo 1 recebe a entrada de um usuário e exibe seus resultados em uma janela de terminal, ela pode ser usada somente em um programa que é executado quando um usuário está presente. Ela não pode ser usada em um programa que é executado automaticamente e recebe entrada de um arquivo, da rede ou de um sensor. Em outras palavras, a função exibir_volume_do_cilindro no exemplo 1 não é reutilizável em outros programas. As funções mais reutilizáveis são aquelas que recebem parâmetros, realizam cálculos e retornam um resultado, mas não realizam entrada e saída do usuário.

A lista de parâmetros no cabeçalho de uma função contém dados armazenados em variáveis que a função precisa para concluir sua tarefa. Um parâmetro é uma variável cujo valor vem de fora da função. Uma forma de inserir dados em uma função é pedir ao usuário por meio da função embutida input. Outra maneira de obter informações de entrada em uma função é por meio dos parâmetros da função. Receber dados por meio de parâmetros é muito mais flexível do que pedir dados ao usuário, porque os dados podem vir do usuário, de um arquivo em um disco rígido, da rede, de um sensor ou até mesmo de outra função.

O exemplo 2 contém outra versão da função exibir_volume_do_cilindro. Esta segunda versão não obtém o raio e a altura do usuário. Em vez disso, ela recebe a entrada por meio de seus dois parâmetros chamados raio e altura.

# Exemplo 2
import math
# Define uma função chamada exibir_volume_do_cilindro.
def exibir_volume_do_cilindro(raio, altura):
  """Calcula e exibe o volume de um cilindro.
  Parâmetros
  raio: o raio do cilindro
  altura: a altura do cilindro
  Retorna: nada
  """
  # Calcula o volume do cilindro.
  volume = math.pi * raio**2 * altura
  # Exibe o volume do cilindro.
  print(volume)

Como a segunda versão da função exibir_volume_do_cilindro aceita dois parâmetros, ela deve ser chamada com dois argumentos. Assim:

exibir_volume_do_cilindro(2.5, 4.1)

Para retornar um resultado de uma função, use a palavra-chave return seguida do resultado que você deseja retornar à função que faz a chamada.

O exemplo 3 traz uma versão da função que retorna o volume em vez de exibi-lo, tornando-a mais reutilizável. Por isso, o nome foi alterado de exibir_volume_do_cilindro para calcular_volume_do_cilindro.

# Exemplo 3
import math
# Define uma função chamada calcular_volume_do_cilindro.
def calcular_volume_do_cilindro(raio, altura):
  """Calcular e retornar o volume de um cilindro.
  Parâmetros
  raio: o raio do cilindro
  altura: a altura do cilindro
  Retorna: o volume do cilindro
  """
  # Calcula o volume do cilindro.
  volume = math.pi * raio**2 * altura
  # Retorna o volume do cilindro de modo que o
  # volume possa ser usado em outro lugar no programa.
  return volume

Muitas funções que você já usou, como input, float e round, retornam um resultado. Geralmente, esse resultado é armazenado em uma variável para ser usado depois, como neste exemplo:

nome = input("Por favor, digite seu nome: ")

Como a função calcular_volume_do_cilindro no exemplo 3 aceita dois parâmetros e retorna um resultado, ela poderia ser chamada assim:

volume = calcular_volume_do_cilindro(2.5, 4.1)

A Função main Definida pelo Usuário

Em todos os programas Python anteriores que você escreveu no CSE 110 e 111, você escreveu instruções que não estavam em uma função como o programa simples no exemplo 4.

# Exemplo 4
import math
# Obtém o raio e a altura do usuário.
raio = float(input("Digite o raio de um cilindro: "))
altura = float(input("Digite a altura de um cilindro: "))
# Calcula o volume do cilindro.
volume = math.pi * raio**2 * altura
# Exibe o volume do cilindro.
print(f"Volume: {volume:.2f}")
> python exemplo_4.py
Digite o raio em centímetros: 3
Digite a altura em centímetros: 8
Volume: 226.19

Em programas grandes, escrever instruções fora de funções pode levar a uma má organização. Desenvolvedores de software profissionais escrevem instruções dentro de funções sempre que possível. A partir desta lição, você fará o seguinte em cada programa:

  1. Escrever quase todas as instruções dentro de uma função definida pelo usuário.
  2. Escrever uma função definida pelo usuário, chamada main, que contenha as instruções iniciais do seu programa.
  3. Escrever uma ou mais funções definidas pelo usuário que tenham parâmetros, realizem cálculos e outros trabalhos úteis e retornem um resultado ao ponto de chamada.
  4. Escrever uma chamada para a função main na parte inferior do seu programa.

O exemplo 5 contém o mesmo programa Python do exemplo 4, exceto que a maioria das instruções está dentro de uma função definida pelo usuário chamada main.

# Exemplo 5
import math
# Define uma função chamada main.
def main():
  # Obtém o raio e a altura do usuário.
  raio = float(input("Digite o raio de um cilindro: "))
  altura = float(input("Digite a altura de um cilindro: "))
  # Calcula o volume do cilindro.
  volume = math.pi * raio**2 * altura
  # Exibe o volume do cilindro.
  print(f"Volume: {volume:.2f}")
# Inicia este programa
# chamando a função main.
main()
> python exemplo_5.py
Digite o raio em centímetros: 3
Digite a altura em centímetros: 8
Volume: 226.19

Observe a chamada para a função main no exemplo 5 na linha 14. Sem essa chamada para a função main, quando executamos o programa, ele não fará nada. Em todos os seus programas futuros no CSE 111, você escreverá uma função definida pelo usuário chamada main e escreverá uma chamada para main no final do programa.

Um Programa Completo com Funções Definidas pelo Usuário

Se você analisar os exemplos 1 e 5, perceberá que ambos apresentam o mesmo problema: ou seja, tanto a função exibir_volume_do_cilindro no exemplo 1 e main no exemplo 5 não são reutilizáveis, pois ambas recebem a entrada do usuário e exibem a saída no terminal. Uma maneira melhor de escrever o programa nos exemplos 1 e 5 é separá-lo em duas funções, uma chamada main e outra chamada calcular_volume_do_cilindro, conforme mostrado no exemplo 6.

O exemplo 6 contém um programa completo com duas funções, a primeira chamada main, na linha 4, e a segunda chamada calcular_volume_do_cilindro, na linha 14. Na linha 10, a função main chama a função calcular_volume_do_cilindro. Observe que a função calcular_volume_do_cilindro recebe sua entrada por meio de parâmetros e retorna um resultado que torna essa função reutilizável em outros programas, incluindo programas que são executados automaticamente sem um usuário.

# Exemplo 6
import math
# Define a função 
. def main(): # Obtém um raio e uma altura do usuário. raio = float(input("Digite o raio de um cilindro: ")) altura = float(input("Digite a altura de um cilindro: ")) # Chama a função calcular_volume_do_cilindro e armazena # seu valor retornado em uma variável para usar depois. volume = calcular_volume_do_cilindro(raio, altura) # Exibe o volume do cilindro. print(f"Volume: {volume:.2f}") # Define uma função que aceita dois parâmetros. def calcular_volume_do_cilindro(raio, altura): """Calcule e exiba o volume de um cilindro. Parâmetros raio: o raio do cilindro altura: a altura do cilindro Retorna: o volume do cilindro """ # Calcula o volume do cilindro. volume = math.pi * raio**2 * altura # Retorna o volume do cilindro para que # possa ser usado em outro lugar no programa. # O resultado retornado estará disponível onde quer que # esta função seja chamada. return volume # Inicia este programa # chamando a função main. main()
> python exemplo_6.py
Digite o raio em centímetros: 3
Digite a altura em centímetros: 8
Volume: 226.19

As funções mais reutilizáveis são aquelas que têm parâmetros, realizam cálculos e retornam um resultado, mas não realizam entrada e saída do usuário. No exemplo de código anterior, há duas funções, chamadas main e calcular_volume_do_cilindro. A função main é certamente útil no programa, mas não é reutilizável em outros programas porque ela recebe a entrada do usuário e exibe o resultado para o usuário ver. A função calcular_volume_do_cilindro é muito reutilizável em outro programa porque ela não recebe entrada do usuário nem exibe saída. Em vez disso, ela pega dois parâmetros, executa um cálculo e retorna um resultado para a função de chamada. A função calcular_volume_do_cilindro é tão reutilizável que poderia ser incluída em uma biblioteca de funções que calculam a área e o volume de formas geométricas 2D e 3D.

O que acontece quando o computador chama uma função?

Alguns estudantes têm dificuldade em visualizar o que acontece quando o computador chama (executa) uma função. O diagrama a seguir contém o mesmo programa do exemplo 6. Os números circulados mostram a ordem em que os eventos acontecem no computador. Os números e setas verdes no diagrama mostram a ordem em que o computador executa instruções no programa. Os números e setas azuis mostram como os dados fluem dos argumentos para os parâmetros e de um resultado retornado para uma variável.

Diagrama mostrando uma chamada para uma função e um valor retornado por essa função

Um computador executará as instruções do diagrama anterior na seguinte ordem:

  1. A instrução em (1) não está dentro de uma função, então o computador a executa quando o programa começa. A instrução em (1) é uma chamada para a função main que faz com que o computador comece a executar as instruções dentro de main em (2).
  2. Em (2), o computador obtém dois números do usuário.
  3. A instrução em (3) é uma chamada para a função calcular_volume_do_cilindro que faz com que o computador copie os valores nos argumentos r e h nos parâmetros raio e altura respectivamente, então comece a executar as instruções dentro da função calcular_volume_do_cilindro em (5).
  4. Em (5), o computador calcula o volume de um cilindro.
  5. A instrução em (6) é uma instrução de retorno que faz com que o computador pare de executar a função calcular_volume_do_cilindro, retorne o volume computado ao ponto de chamada em (3) e retome a execução de instruções no ponto de chamada.
  6. No ponto de chamada (3), o computador armazena o valor retornado na variável chamada v.
  7. Em (8), o computador exibe o valor que está na variável volume para o usuário ver. Esta é a última instrução na função main, portanto, após executá-la, o computador retoma a execução das instruções após o ponto de chamada (1) para main.
  8. Em (9), não há mais instruções após a chamada para main, então o computador encerra o programa.

Grafos de Chamadas

Legenda para ler um gráfico de chamadas

Um grafo de chamadas é um diagrama que mostra chamadas e retornos de funções dentro de um programa. Um gráfico de chamadas pode ajudar a visualizar como um programa é dividido em funções. Em um gráfico de chamadas, o círculo vazio mostra onde o computador começa a executar um programa. Um retângulo arredondado representa uma função. Uma seta sólida representa uma chamada de uma função para outra. A seta tracejada indica o valor que uma função retorna para a função que a chamou.

O grafo de chamadas abaixo mostra as chamadas de função e os retornos do programa no exemplo 6. No grafo de chamadas, vemos que o computador começa a executar o programa chamando a função main. Ao executar a função main, o computador chama as funções input e float. Em seguida, o computador chama a função calcular_volume_do_cilindro. Por fim, o computador chama a função print. No diagrama, é possível ver que as funções main e print não retornam um valor. A função print exibe resultados para o usuário ver, mas não retorna nada.

Grafo de chamadas para o programa no exemplo 6.

Resumo

Uma função é um conjunto de instruções que executa uma tarefa específica. Quando você cria essa função, ela é chamada de função definida pelo usuário. Para isso, siga este modelo:

def nome_da_funcao(param1, param2, … paramN):
  """string de documentação"""
  instrucao1
  instrucao2
  ⋮
  instrucaoN
  return valor

Para chamar uma função definida pelo usuário, escreva um código que siga este modelo:

nome_da_variavel = nome_da_funcao(arg1, arg2, … argN)

As funções mais reutilizáveis são aquelas que recebem parâmetros, realizam cálculos e retornam um resultado, mas não realizam entrada e saída do usuário. Em todos os seus programas futuros no CSE 111, você terá uma função definida pelo usuário chamada main e terá uma chamada para main no final do programa.

É extremamente importante que você saiba escrever e chamar funções. Depois de assistir aos vídeos e ler este conteúdo de preparação, se os conceitos ainda parecerem confusos ou vagos para você, ore e peça ao Pai Celestial para ajudar você a entendê-los. Depois assista aos vídeos e leia os conceitos novamente.

Atividade

Objetivo

Avalie seu conhecimento sobre escrever suas próprias funções com parâmetros e depois chamar essas funções com argumentos.

Declaração do Problema

Muitos proprietários de veículos registram o consumo de combustível de seus veículos como uma forma de monitorar a saúde do veículo. Se o consumo de combustível de um veículo aumentar repentinamente, provavelmente há algo errado com o motor ou com o sistema de transmissão do veículo. No Brasil, como em outros países, o consumo é calculado em quilômetros por litro. Nos Estados Unidos, o consumo é medida em milhas por galão.

A fórmula básica para calcular o consumo de combustível é:

consumo =
fim - início
quantidade de combustível
  • início e fim representam as leituras inicial e final do odômetro
  • quantidade de combustível corresponde ao total de combustível consumido no trajeto.
  • Em algumas situações, especialmente ao comparar padrões internacionais, é necessário converter as unidades. Para isso, utilizamos as seguintes fórmulas:

    Para converter litros em galões:

    galões = litros × 0.26417
  • litros representa a quantidade de combustível consumida em litros, e galões indica o valor correspondente em galões.
  • Para converter quilômetros em milhas:

    distância em milhas =
    distância em quilômetros
    1.609

    Observação: Em muitos países, incluindo o Brasil, a vírgula é usada como separador decimal (ex.: 2,54). No Python — assim como em outras linguagens — o separador decimal usado é o ponto. Por isso, mantenha 0.26417 e 1.609 exatamente assim; trocar o ponto por vírgula mudaria o valor.

    Tarefa

    Escreva um programa em Python que peça três números ao usuário:

    1. O valor inicial do odômetro em quilômetros
    2. O valor final do odômetro em quilômetros
    3. A quantidade de combustível em litros

    Seu programa deve calcular e exibir o consumo de combustível tanto em milhas por galão quanto em quilômetros por litro. Além disso, o programa deve conter três funções com os seguintes nomes:

    1. main
    2. quilometros_por_litro
    3. milhas_por_galao

    Todas as entradas do usuário e funções print devem estar na função main. Ou seja, as funções quilometros_por_litro e milhas_por_galao não devem chamar as funções input ou print.

    Documentação Útil

    Etapas

    Copie e cole o código a seguir em um novo programa chamado consumo_de_combustivel.py. Use esse código como modelo ao escrever o seu próprio programa e criar cada uma das três funções.

    def main():
      # Obtém do usuário o valor inicial do odômetro em quilômetros.
      # Obtém do usuário o valor final do odômetro em quilômetros
      # Obtém do usuário a quantidade de combustível em litros.
      # Chama a função quilometros_por_litro, calcula o consumo em
      # quilômetros por litro e armazena
      # o resultado em uma variável chamada kml.
      # Chama a função milhas_por_galao para converter o valor 
      # de quilômetros em milhas, de litros em galões e calcular
      # o consumo em milhas por galão.
      # Armazena o resultado em uma variável chamada mpg.
      # Exibe os resultados para o usuário.
      pass
      
    def quilometros_por_litro(valor_inicial, valor_final, quantidade_de_litros):
      """ 
      Calcula e retorna o consumo em quiLômetros por litro
      Parâmetros
        valor_inicial: O valor inicial do odômetro em quilômetros.
        valor_final: O valor final do odômetro em quilômetros.
        quantidade_de_litros: A quantidade de combustível em litros.
      Retorna: Consumo de combustível em quilômetros por litro.
      """
      return
    
    def  milhas_por_galao(valor_inicial, valor_final, quantidade_de_litros):
      """
      Converte litros e quilômetros para galões e milhas
      e retorna o consumo em milhas por galão
      Parâmetros
          valor_inicial: O valor inicial do odômetro em quilômetros
          valor_final: O valor final do odômetro em quilômetros
          quantidade_de_litros: A quantidade de combustível em litros
      Retorna: Consumo de combustível em milhas por galão.
      """
      return
    
    # Chama a função main para que
    # o programa seja executado.
    main()

    Procedimento de Teste

    Verifique se seu programa funciona corretamente seguindo cada etapa deste procedimento de teste:

    1. Execute seu programa e digite as entradas mostradas abaixo. Certifique-se de que a saída do seu programa corresponda à saída abaixo.
      > python consumo_de_combustivel.py
      Qual o valor inicial do odômetro em quilômetros? 30000
      Qual o valor final do odômetro em quilômetros? 30150
      Qual a quantidade de combustível consumida em litros? 11.2
      13.4 quilômetros por litro
      31.51 milhas por galão

    Exemplo de Solução

    Quando terminar seu programa, consulte o exemplo de solução para comparar com o seu.

    Primeiro, procure concluir o programa sem olhar o exemplo de solução. No entanto, se já tiver trabalhado nele por bastante tempo e ainda estiver com dificuldades, sinta-se à vontade para usá-lo como apoio para finalizar seu programa.

    Gráfico de Chamadas

    O gráfico de chamadas a seguir mostra as chamadas e retornos de função no exemplo de solução para esta tarefa. Neste gráfico de chamadas, vemos que o computador começa a executar o programa de exemplo chamando a função main. Ao executar a função main, o computador chama as funções input e float. Em seguida, o computador chama as funções quilometros_por_litro e milhas_por_galao. Por fim, o computador chama a função print, que é o fim do programa.

    Gráfico de chamadas de função para esta tarefa

    Ponderar

    Depois de terminar esta tarefa, comemore, pois você escreveu um programa em Python com três funções definidas pelo usuário, chamadas main, quilometros_por_litro e milhas_por_galao. É importante que você saiba escrever suas próprias funções? Por quê?

    Links Úteis: