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.

  1. Implemente um programa que utiliza a função first_last para testá-la com diferentes valores.
  2. 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

Author: Pedro Belin Castellucci

Created: 2024-06-03 seg 09:19

Validate