Funções podem chamar outras funções¶
É importante entender que cada uma das funções que escrevemos pode ser usada e chamada de outras funções criadas por nós. Isso é uma das principais formas que cientistas da computação utilizam para resolver problemas grandes: dividindo eles em problemas menores. O processo de dividir um problema em subproblemas menores é chamado de decomposição funcional.
Aqui está um exemplo simples de decomposição funcional, usando duas funções.
A primeira função é a nossa conhecida quadrado
, que calcula o quadrado de um
determinado número. A segunda função é chamada somaQuadrados
, e faz uso de quadrado
para calcular a soma de três números que foram elevados ao quadrado.
(sumofquadrados)
Apesar de ser uma ideia bem simples, na prática esse exemplo
ilustra vários conceitos importantes em Python, incluindo os de variáveis locais
e globais com passagem de parâmetros. Note que ao executar passo a passo, o codelens
deixa em negrito as linhas 1 e 5 à medida em que as funções são definidas.O corpo
de quadrado
não é executado até que seja chamado da função somaQuadrados
pela
primeira vez na linha 6. Também repare que na chamada de quadrado
há dois grupos
de variáveis locais, um para quadrado
e um para somaQuadrados
. Ao executar passo a passo
você irá notar que x
e y
são variáveis locais em ambas as funções, e podem até ter
valores diferentes. Isso demonstra que mesmo tendo o mesmo nome, elas são, efetivamente,
muito diferentes.
Vejamos outro exemplo que usa duas funções. Este exemplo ilustra uma técnica importante utilizada em Ciência da Computação para resolver problemas, chamada generalização. Imagine que desejamos criar uma função para desenhar um quadrado. A etapa de generalização é se dar conta que um quadrado é apenas um tipo especial de retângulo.
Para desenhar um retângulo, precisamos ser capazes de chamar uma função com argumentos diferentes para largura e altura. Diferentemente do quadrado, não podemos repetir a mesma coisa 4 vezes, uma vez que os quatro lados não são necessariamente iguais. Porém, os lados de cima e de baixo são iguais, e o mesmo ocorre com os lados esquerdo e direito. Dessa forma, o código que desenha um retângulo pode ser simplificado assim:
def desenhaRetangulo(t, w, h):
"""Faz a tartaruga t desenhar um retângulo de largura w e altura h."""
for i in range(2):
t.forward(w)
t.left(90)
t.forward(h)
t.left(90)
Os nomes dos parâmetros foram escolhidos como letras para garantir que não há confusão. Em programas reais, é sempre melhor usar nomes mais adequados. O detalhe é que o programa não “entende” que você está desenhando um retângulo ou que os parâmetros representam a largura e altura. Conceitos como “retângulo”, “largura” e “altura” só têm significado para humanos. Eles não são conceitos que um programa ou um computador entenda.
Se você lembrar das minhas aulas, pensamento computacional envolve a busca por padrões conhecidos. No código acima fizemos isso, até certo ponto. Nós não apenas desenhamos quatro lados: nós nos demos conta que poderíamos desenhar o retângulo como duas metades, e usamos uma repetição para repetir esse padrão duas vezes.
Mas agora talvez perceberíamos que um quadrado é um tipo especial de retângulo. Um quadrado simplesmente usa o mesmo valor para largura e altura. Como nós já temos uma função que desenha um retângulo, basta utilizá-la:
def desenhaQuadrado(t, tam): # uma nova versão de desenhaQuadrado
desenhaRetangulo(t, tam, tam)
Aqui está o exemplo completo:
Há algumas coisas a observar aqui:
- Funções podem chamar outras funções
- Reescrevendo
desenhaQuadrado
dessa forma exibe o relacionamento que descobrimos. - Um chamador dessa função poderia fazer desenhaQuadrado(tess, 50). Aos parâmetros
dessa função,
t
etam
, são associados os valores do objeto tess e o número inteiro 50, respectivamente. - No corpo da função,
t
andtam
são como qualquer outra variável. - Quando a chamada é feita para
desenhaRetangulo
, os valores nas variáveist
etam
são acessados primeiro, e então a chamada acontece. Dessa forma, quando entramos no topo da função desenhaRetangulo, sua varíavelt
é associada ao objeto tess e ambasw
eh
recebem o valor 50.
Até este ponto, pode não estar tão claro porque vale a pena criarmos todas as novas funções. Na verdade há várias razões, mas esse exemplo demonstra três delas:
- Criar uma nova função nos dá uma oportunidade de dar um nome a um bloco de comandos. Funções podem simplificar um programa, escondendo um cálculo complexo atrás de um comando simples. A função (incluindo seu nome) pode capturar seu pensamento computacional, ou abstração do problema.
- Criar uma nova função pode deixar um programa menor, eliminando código repetido.
- Algumas vezes você pode escrever funções que permitem resolver um problema específico através de uma solução mais genérica.