Funções


Funções

É frequente decompormos um procedimento obtendo partes menores que podem ser resolvidas de forma independente do fio principal do programa.
Por exemplo, desenhar um gráfico ou histograma pode ser parte de um programa maior que analisa massas de dados. Produzir este desenho ou representação gráfica em sí é um procedimento, que pode e deve ser programado independente do programa de análise de dados.
O programa principal simplesmente invoca a execução deste procedimento auxiliar passando-lhe dados relevantes, tais como as variáveis cujos valores devem ser desenhados, etc, e o procedimento auxiliar produz a representação gráfica desejada.
A forma como este tipo de procedimento auxiliar é codificado é a de função.

Porque usar funções? O que se ganha com isto?
Muita coisa mesmo:
  1. fica mais fácil construir um procedimento como diversos procedimentos menores montados num todo.
  2. cada função pode ser programada com menos erros por ter um objetivo mais focalizado
  3. é mais fácil depurar funções menores do que um grande programa monolítico
  4. funções podem ser reutilizadas em outros programas com enorme economia de esforço

Uma função é definida com um nome, um corpo contendo seus comandos e uma lista de dados que lhe são fornecidos no início, chamados de argumentos. Um comando que ainda não vimos é usado em funções para retornar valores calculados durante sua execução: o comando return.
Vejamos exemplos em Python:
In [1]:
def total(L):
    '''função que recebe como argumento uma lista L de numeros e retorna a soma dos números da lista'''
    soma = 0
    for x in L:
        soma = soma + x
    return soma
In [2]:
# soma esta lista
uma_lista = [1,2,3,4,5,6]
total(uma_lista)
Out[2]:
21
As variáveis definidas no corpo de uma função são ditas locais e são apagadas automaticamente quando a função termina de executar e retorna.
Em contraste variáveis definidas fora de qualquer função são chamadas variáveis globais.
A diferença maior entre os dois tipos de variáveis é que variáveis locais são visíveis exclusivamente dentro do corpo de determinada função, enquanto variáveis globais são visíveis em qualquer parte do programa, inclusive dentro de funções (mas é desaconselhado usar variáveis globais dentro de funções! Isto iria contra o próprio propósito de ter funções em primeiro lugar.)
Toda informação global que uma função precisa deve ser-lhe passada via argumentos no ponto onde ela for chamada. Quando a função começa a executar a primeira coisa que acontece é que os valores dos argumentos são copiados em variáveis locais de mesmo nome para uso dentro da função.
Aqui é importante lembrar que o valor de uma variável é uma referência a algum objeto. Portanto quando os argumentos são copiados em variáveis locais, suas cópias locais passam a referenciar os mesmos objetos. Se estes objetos forem modificáveis, tipo uma lista, a variável externa passa a ver seu objeto também modificado.
Vejamos um exemplo deste ponto:
In [7]:
def boba(x):
    x = 3
    
n = 2
boba(n)
n
Out[7]:
2
In [6]:
def outra(L):
    # aqui L é uma lista
    L[0] = 'mudei'
    
lst = [1,2,3]
outra(lst)
lst
Out[6]:
['mudei', 2, 3]
Toda função deve retornar algum valor. Entretanto as funções acima parecem não retornar nada. O que ocorre é que se não há um comando explicito return então o Python implicitamente assume um valor default de retorno equivalente a "nada".
Este valor é o None, usado sempre que um retorno de função qualquer for vazio, ou "nada". None pode ser usado explicitamente para indicar isto ao usuário de uma função.
In [13]:
def retorna_par(L):
    '''retorna um numero par da lista L de numeros'''
    for x in L:
        if x % 2 == 0:
            return x

L = [1,3,7,9]
n = retorna_par(L)
print(n)
None
Uma função em sí tambem é um objeto do Python e pode ser manipulada de acordo. Por exemplo:
In [15]:
f = retorna_par         # f passa a referenciar a função retorna_par
L = [1,2,3,5,7]
n = f(L)
n
Out[15]:
2
No mesmo espírito podemos passar funções nos argumentos de outras funções:
In [24]:
def aplica(f, L):
    '''aplica uma função f em cada elemento de uma lista'''
    return [f(x) for x in L]


def par(x):
    # retorna teste se x é numero par
    return x%2 == 0

def impar(x):
    # retorna teste se x é número impar
    return x%2 != 0


L = [1,2,3,4,5]

aplica(par, L)
Out[24]:
[False, True, False, True, False]
In [25]:
aplica(impar, L)
Out[25]:
[True, False, True, False, True]
Nos documentos oficiais são dados mais detalhes sobre argumentos de funções, listas de argumentos, keyword arguments e valores default.
In [ ]:
 

No comments:

Post a Comment