Subprogramação
Table of Contents
1. Introdução
Parte do trabalho de programação é desenvolver códigos da maneira mais eficiente possível. Parte dessa eficiência está relacionada ao reúso de fragmentos de código que tipicamente realizam tarefas simples (ou frequentes). Um dos mecanismos mais simples para reúso de código em Python é a função.
O Python (assim como outras linguagens de programação) já disponibiliza diversas funções. Inclusive, estamos utilizando algumas delas desde o início do curso. Alguns exemplos de funções embutidas no Python são (uma lista completa pode ser vista neste link).
print
input
len
min
max
range
sum
Para utilizar uma função basta fornecer os argumentos necessários, para chamá-la.
first_name = input("What is your first name?") last_name = input("What is your last name?") print("Hello", first_name, last_name)
Além das funções disponibilizadas, podemos criar nossas próprias funções.
2. Criando uma função
A sintaxe para criação de funções é exemplificada no seguinte trecho.
def nome_da_funcao(arg1, arg2, ...): comandos return resultado # Opcional
Note que a palavra-chave def
define um novo bloco, isto é, todos os
comandos que compõem a função devem estar com a identação correta. A
palavra-chave def
é seguida do nome da função. É recomendado que o
nome das funções indiquem alguma ação (outras convenções neste
link). Então, segue uma lista de arguments (arg1
, arg2
,
etc…). Os argumentos marcam os dados que a função deve receber para
realizar as suas operações. Por fim, o comando return
indica um
ponto de saída da função e o seu
retorno. O retorno de uma função define qual é efetivamente o seu
resultado, que pode ser utilizado pelo código que chamou a função. Por
exemplo,
- a função
input
, tem como retorno a string digitada pelo usuário, - a função
len
, tem como retorno o número de elementos da coleção utilizada como argumento.
O retorno é opcional, a função print
, por exemplo, realiza a ação de
imprimir na tela a string fornecida como argumento, mas não retorna
nenhuma função.
O comando return
, ao ser executado, termina a função. Isto é, nenhum
outro comando da função serão realizado após o return
. De forma
análoga ao comando break
em laços de repetição.
2.1. Nossa primeira função
Como exemplo, vamos construir uma função que recebe dois valores e realiza a soma dos dois valores e retorna o resultado.
def my_sum(x, y): return x + y
Identifique os argumentos e o retorno na função my_sum
.
O código a seguir utiliza a função my_sum
para calcular a média
aritmética simples de duas notas, \(P1\) e \(P2\).
def my_sum(x, y): return x + y p1 = int(input("Digite nota da P1: ")) p2 = int(input("Digite nota da P2: ")) print("Sua media ", my_sum(p1, p2)/2)
Note que o nome dos argumentos da função, x
e y
, não são os mesmos
dos parâmetros, p1
e p2
. A ligação entre os parâmetros e os
argumentos é feita por interpretador/compilador. O programador está
livre para definir os nomes de cada um.
Defina o que será impresso no código a seguir.
def my_sum(x, y): return x + y dados = input("Digite dois numeros separados por espaco: ") numeros = dados.split() print("A soma e' ", my_sum(numeros[0], numeros[1]))
2.2. Sendo mais genérico
Uma potencial melhoria para a função my_sum
é que ela seja capaz de
lidar não apenas com dois valores, mas com uma lista de
valores. Para isso, podemos definir a seguinte função.
def my_sum_list(L): acc = 0 for x in L: acc += x return acc
É crítico que cada função seja testada com diferentes argumentos. Nunca utilize uma função sem estar confiante de que a implementação está correta.
Implemente um programa que utiliza a função my_sum_list
com
diferentes valores para conferir o seu resultado. Garanta que os
resultado é o mesmo da função sum
para valores numéricos.
Uma facilidade do Python é o retorno de múltiplos valores. Observe o exemplo a seguir, de uma função que recebe uma lista e retorna o primeiro e o último valor dessa lista.
def first_last(L): return L[0], L[-1]
Considere os itens a seguir.
- Implemente um programa que utiliza a função
first_last
para testá-la com diferentes valores. - Determine o que acontece com a função
first_last
no caso dela ser utilizada com uma lista vazia. Discuta se esse é o comportamento desejado.
3. Passagem de parâmetros por valor e por referência
Considere o programa a seguir, tente deduzir o que será impresso pelos
comandos print
.
def foo(x, y): x = x + 1 y = y + 1 return x + y x = 10 y = 20 r = foo(x, y) print(x) print(y) print(r)
se você respondeu que a impressão seria
11 21 32
você está incorreto. Esse é um erro comum para quem está começando a programar e está relacionado com escopo e passagem de parâmetros para funções.
No comando r = foo(x, y)
, acontece o seguinte. Os valores de x
e
y
são copiados para a função foo
para preencher as variáveis x
e y
desta função. É importante entender que a associação dos valores
10
e 20
com a dos valores de x
e y
dentro da função foo
não
está relacionada com o nome das variáveis em si. Variáveis de tipos
int
e float
possuem esse comportamento de passagem por valor.
Na passagem de parâmetros por valor, é feita uma cópia dos valores para os respectivos parâmetros das funções.
Vamos analisar o seguinte exemplo. Tente prever o que será impresso.
def foo(L): L.append(10) x = [1, 2, 3, 4] foo(x) print(x)
Listas em Python são passadas por referência, na prática, isso
significa que a lista L
no escopo da função foo
é a mesma lista
que está fora, apenas referenciada com outro nome.
Na passagem de parâmetros por referência, é feita uma cópia do endereço das variáveis e os mesmos espaços de memória são acessados.
3.1. A realidade é um pouco mais complicada
A explicação apresentada na verdade é uma simplificação do processo utilizado pelo Python. O mecanismo real é mais sofistificado, para evitar cópias de valores desnecessariamente. Uma material com uma explicação mais detalhada pode ser explorado aqui.
4. Referências e outros materiais
- Payne, James R. Python for Teenagers: Learn to Program Like a Superhero! Apress, 2019.
- https://realpython.com/python-pass-by-reference/