Python para Desenvolvedores

2ª edição, revisada e ampliada

Capítulo 6: Funções


Funções são blocos de código identificados por um nome, que podem receber parâmetros pré-determinados.

No Python, as funções:

  • Podem retornar ou não objetos.
  • Aceitam Doc Strings.
  • Aceitam parâmetros opcionais (com defaults). Se não for passado o parâmetro será igual ao default definido na função.
  • Aceitam que os parâmetros sejam passados com nome. Neste caso, a ordem em que os parâmetros foram passados não importa.
  • Tem namespace próprio (escopo local), e por isso podem ofuscar definições de escopo global.
  • Podem ter suas propriedades alteradas (geralmente por decoradores).

Doc Strings são strings que estão associadas a uma estrutura do Python. Nas funções, as Doc Strings são colocadas dentro do corpo da função, geralmente no começo. O objetivo das Doc Strings é servir de documentação para aquela estrutura.

Sintaxe:

def func(parametro1, parametro2=padrao):
    """
    Doc String
    """
    <bloco de código>
    return valor

Os parâmetros com default devem ficar após os que não tem default.

Exemplo (fatorial com recursão):

In [2]:
# Fatorial implementado de forma recursiva

def fatorial(num):

    if num <= 1:
        return 1
    else:
        return(num * fatorial(num - 1))

# Testando fatorial()
print fatorial(5)
120

Exemplo (fatorial sem recursão):

In [3]:
def fatorial(n):

    n = n if n > 1 else 1
    j = 1
    for i in range(1, n + 1):
        j = j * i
    return j

# Testando...
for i in range(1, 6):
    print i, '->', fatorial(i)
1 -> 1
2 -> 2
3 -> 6
4 -> 24
5 -> 120

Exemplo (série de Fibonacci com recursão):

In [4]:
def fib(n):
    """Fibonacci:
    fib(n) = fib(n - 1) + fib(n - 2) se n > 1
    fib(n) = 1 se n <= 1
    """
    if n > 1:
        return fib(n - 1) + fib(n - 2)
    else:
        return 1

# Mostrar Fibonacci de 1 a 5
for i in [1, 2, 3, 4, 5]:
    print i, '=>', fib(i)
1 => 1
2 => 2
3 => 3
4 => 5
5 => 8

Exemplo (série de Fibonacci sem recursão):

In [5]:
def fib(n):
    """Fibonacci:
    fib(n) = fib(n - 1) + fib(n - 2) se n > 1
    fib(n) = 1 se n <= 1
    """
    
    # Dois primeiros valores
    l = [1, 1]
    
    # Calculando os outros
    for i in range(2, n + 1):
        l.append(l[i -1] + l[i - 2])
        
    return l[n]

# Mostrar Fibonacci de 1 a 5
for i in [1, 2, 3, 4, 5]:
    print i, '=>', fib(i)
1 => 1
2 => 2
3 => 3
4 => 5
5 => 8

Exemplo (conversão de RGB):

In [6]:
def rgb_html(r=0, g=0, b=0):
    """Converte R, G, B em #RRGGBB"""

    return '#%02x%02x%02x' % (r, g, b)

def html_rgb(color='#000000'):
    """Converte #RRGGBB em R, G, B"""

    if color.startswith('#'): color = color[1:]

    r = int(color[:2], 16)
    g = int(color[2:4], 16)
    b = int(color[4:], 16)

    return r, g, b # Uma sequência

print rgb_html(200, 200, 255)
print rgb_html(b=200, g=200, r=255) # O que houve?
print html_rgb('#c8c8ff')
#c8c8ff
#ffc8c8
(200, 200, 255)

Observações:

  • Os argumentos com padrão devem vir por último, depois dos argumentos sem padrão.
  • O valor do padrão para um parâmetro é calculado quando a função é definida.
  • Os argumentos passados sem identificador são recebidos pela função na forma de uma lista.
  • Os argumentos passados com identificador são recebidos pela função na forma de um dicionário.
  • Os parâmetros passados com identificador na chamada da função devem vir no fim da lista de parâmetros.

Exemplo de como receber todos parâmetros:

In [7]:
# *args - argumentos sem nome (lista)
# **kargs - argumentos com nome (dicionário)

def func(*args, **kargs):
    print args
    print kargs

func('peso', 10, unidade='k')
('peso', 10)
{'unidade': 'k'}

No exemplo, kargs receberá os argumentos nomeados e args receberá os outros.

O interpretador tem definidas algumas funções builtin, incluindo sorted(), que ordena sequências, e cmp(), que faz comparações entre dois argumentos e retorna -1 se o primeiro elemento for maior , 0 (zero) se forem iguais ou 1 se o último for maior. Essa função é usada pela rotina de ordenação, um comportamento que pode ser modificado.

Exemplo:

In [8]:
dados = [(4, 3), (5, 1), (7, 2), (9, 0)]

# Comparando pelo último elemento
def _cmp(x, y):
    return cmp(x[-1], y[-1])

print 'Lista:', dados

# Ordena usando _cmp()
print 'Ordenada:', sorted(dados, _cmp)
Lista: [(4, 3), (5, 1), (7, 2), (9, 0)]
Ordenada: [(9, 0), (5, 1), (7, 2), (4, 3)]

O Python também possui como builtin a função eval(), que avalia código (fonte ou objeto) retornando o valor.

Exemplo:

In [9]:
print eval('12. / 2 + 3.3')
9.3

Com isso é possível montar código para ser passado para o interpretador durante a execução de um programa. Esse recurso deve ser usado com cuidado, pois código montados a partir de entradas do sistema abrir brechas de segurança.

In [1]:
 
Out[1]: