Programação Modular

O que iremos cobrir?
  • O que são módulos
  • Funções e módulos
  • Usando ficheiros de módulos
  • Escrever as nossas próprias funções e os nosso próprios módulos

O que é um módulo?

O quarto elemento da programação é o programação modular. Não é uma coisa que seja absolutamente necessária, porque até com o que já foi aprendido até agora serias capaz de escrever programas muito impressionantes. Contudo a medida que os programas vão ficando cada vez maiores torna-se cada vez mais difícil a manutenção, tornando assim mais difícil o debug se determinada parte do código estiver com erros. De uma certa forma iremos precisar de nos abstrair por forma a podermos concentrar-nos problemas que estamos a tentar resolver do que realmente ficarmos encalhados a pensar no funcionamento do computador propriamente dito. Por isso tanto o Python, como o BASIC já vem com certas capacidades construídas no core do programa (built-ins. Alguns desses built-ins fazem exactamente isso, lidam com o hardware do computador, executam certas tarefas que se tem de executar com alguma frequência.

O papel da programação modular é permitir o próprio programa estender essas capacidades built-ins. Ou seja criamos módulos que no fundo são pequenos programas em si, e depois juntamos isso a nossa linguagem de programação, é como inventar uma expressão nova para nossa lingua-mãe. A programação modular teve a sua primeira forma sob a capa subroutine que era um pequeno bloco de código que podia saltar (tipo o GOTO que mencionei à pouco) e quando esse bloco de código acabasse de cumprir o papel para fora chamado ele voltava ao seu ponto de partida. Este tipo especifico de programação modular acabou por ficar conhecido como uma procedure ou então função. No Python como em outras linguagens a palavra módulo acabou por assumir outro significado, à que iremos dar atenção daqui a um pouco, mas por agora olhemos para as funções com um pouco mais de cuidado.

Usando funções

Antes de considerarmos como criar funções, vamos ver como usar as muitas funções que já vem com a linguagem de programação (por vezes conhecido como Biblioteca).

Nós já vimos anteriormente, na secção de sobre os operadores, algumas funções. Agora o que vamos considerar é o que eles têm em comum e como as podemos usar em programas nossos.

Isto é a estrutura básica de uma função:

umValor = aFuncao(umArgumento, outro, etc...)

Isto é, uma variável assume um valor obtido pela chamada de uma função. A função pode aceitar 0 ou muitos argumentos que ele trata como variáveis internas. Funções podem chamar por outras funções internamente. Mas agora vamos ver alguns exemplos nas nossas varias linguagens para ver como tudo isto funciona:

BASIC: MID$(str$,n,m)

Isto serve para imprimir o caracter m, começando no n na string str$. (lembras-te que nomes acabando em $ em BASIC significam string).

time$ = "DIA NOITE TARDE"
PRINT "Bom";MID$(time$,8,8)

Isto há-de Imprimir "Bom NOITE". Neste caso seria mais correcto ser Boa noite, mas enfim, perceberam.

BASIC: ENVIRON$(str$)

Isto irá imprimir a variável de ambiente str$.

PRINT ENVIRON$("PATH")

Isto irá imprimir a variável PATH(que podemos encontrar no ficheiro autoexec.bat).

Tcl: llength L

irá devolver a lista contida em L

set a {"primeiro" "segundo" "terceiro"} # uma lista com 3 elementos
puts [llength $a]  # o output é '3'

Nota: Quase tudo dentro do Tcl é uma função (ou se preferirem, um comando). Isto pode levar por vezes a sintaxes muito bizarras mas torna os programas do Tcl muito fáceis de interpretar para computador. Isto é importante porque o Tcl significa Tool Control Language (linguagem de ferramentas de controlo, numa tradução muito livre, o Tcl foi concebido com o para ser introduzido aplicações como uma linguagem macro, tal como o Visual BASIC for Aplications dos produtos Microsoft. Também podes utilizar o Python da mesma forma, mas o Tcl continua a ser unico porque tem as características já de natureza, como uma linguagem macro.

Python: pow(x,y)

x = 2   #  vamos usar o 2 como o nosso número base
for y in range(0,11):
   print pow(x,y)    # elevamos o 2 ao y

Aqui criamos os valores de y (de 0 a 10) e chamamos a função built-ins pow() com 2 argumentos: x e y. Em cada vez que chamamos a função os valores correntes do x e do y são substituídos e o resultado é disposto no ecrã.

Note: o operador ** tem as mesmas características que o pow().

Python: dir(m)

Uma outra função muito útil que já vem com o Python é o dir que, quando passado a um módulo, devolve-nos uma lista de nomes válidos - na maior parte das vezes nomes de funções - desse módulo. Experimenta fazer isto:

print dir(__builtin__)

Note: por forma a que possas utilizar o dir em qualquer outro módulo, terás que import o módulo primeiro porque senão o Python se irá queixar que não esta a reconhecer o nome.

Agora antes de avançarmos ainda mais um pouco, vamos falar sobre os módulos do Python.

Usando módulos

O Python é uma linguagem extraordinariamente extensível (tal como o Tcl) na qual podes adicionar novas funções importando módulos. Veremos dentro de breve como criar um módulo, mas para já vamos ver como podemos usar os que já vêem incluídos no Python..

sys

O sys já é um velho conhecido nosso. Já foi utilizado quando utilizamos o exit() para sairmos do Python. Mas o sys não se resume apenas a isso, existem uma quantidade de coisas a que podemos ter acesso, para isso basta simplesmente digitar import sys:

import sys # torna a função disponível
sys.exit() # temos que usar os prefixo 'sys'
Quando temos a certeza que iremos usar bastante uma das funções, e sabemos de antemão que nenhuma das funções que vamos criar há-de ter os mesmos nome, podemos utilizar este pequeno truque para poupar trabalho:
from sys import *  # importa todos nomes em sys
exit() # agora já podemos usa-lo sem especificar o prefixo sys'

Outros módulos, e o que eles nos podem oferecer

tu podes importar e usar qualquer módulo da forma como acabamos de exemplificar, e isto também se aplica aos módulos que futuramente venhas a criar, e é isso que iremos ver dentro de pouco. Mas antes pensei em dar-te aqui uma pequena tabela de módulos que já vem incluídos no Python e que eles te podem oferecer:

Nome do MóduloDescrição
sys Permite uma interacção com o sistema do Python:
  • exit() - exit!
  • argv - acesso a linha de comandos
  • path - acesso ao path
  • ps1 - para mudar '>>>' prompt do Python!
os Permite uma interacção com o sistema operativo:
  • open - para abrir um ficheiro
  • system - para executar um comando do sistema
  • mkdir - para criar uma directoria
  • getcwd - para encontrar a directoria de trabalho
string Permite a manipulação de Strings
  • atoi/f/l - converte uma string em /float/long
  • find - para encontrar uma substring
  • split - para dividir as palavras
  • upper/lower - mudar de maiúsculas para minúsculas e vice-versa
re Permite uma manipulação de strings com expressões do
Unix
  • search - encontra um padrão dentro de uma string
  • match - procura apenas no inicio
  • split - separa em campos por padrões
  • sub,subn - substitui uma string
math Acesso muitas funções da matemática:
  • sin,cos etc - funções trigonométricas
  • log,log10 - logaritmos naturais e decimais
  • ceil,floor - tecto e chão
  • pi, e - constantes naturais
time Acesso a funções de data e hora
  • time - mostra as horas (em segundos)
  • gmtime - converte as horas de segundos para UTC (GMT)
  • localtime - converte para as horas locais
  • mktime - inverso das horas locais
  • sleep - coloca o programa em pausa por n segundos

Mas isto que acabas de ver é apenas a ponta do iceberg. Existem dúzias (ou paletes, como preferirem) de módulos que estão incluídos no Python, e uns outros tantos dos quais podes fazer um download. ( boa fonte é Vaults of Parnassus.) Se olhares com atenção para a documentação do Python facilmente como podes fazer programação para a Internet, gráficos, construir uma base de dados, etc....

O que é importante aperceber-nos aqui é que a maior parte das linguagens de programação têm as funções básicas construídas dentro delas - ou como built-ins ou então como parte das suas bibliotecas - portanto verifica sempre com muita atenção a documentação de uma linguagem antes de construir uma função, porque pode ser que alguém já tenha sido gentilmente o suficiente para fazer isso por nós. Então, agora, só falta sabermos como construir os nossos próprios módulos (já não era sem tempo).

Definindo as nossas próprias funções

O.k., agora que já sabemos como usar as funções existentes, esta na altura de aprendermos como criar as nossas próprias funções. E como é que fazemos isso? Simplesmente a declara-mos. Isto é nós escrevemos um statement que irá dizer ao interprete que estamos a definir um bloco de código que poderá ser inserido numa outra parte qualquer de programa se assim o desejarmos.

Então agora passemos a prática e vamos criar um uma função que irá imprimir a tabela de multiplicação de qualquer valor de nós usamos como argument. no BASIC há-de ser assim:

SUB TABUADA(N%)
FOR I = 1 TO 12
    PRINT I; "x"; N%; "="; I * N%
NEXT I
END SUB

E chamamos pela função assim::

PRINT "Aqui esta a tabuada do 7..."
TIMES(7)

Note: Ao criar a função, não só definimos um dos parâmetros como N%, ao qual depois demos o valor de 7. O que aconteceu foi que a variável local dentro da função assumiu o valor de 7 quando foi chamado. Somos livres para definir o número de parâmetros que queremos incluir numa função, mas atenção que quando chamamos o programa temos de incluir todos os valores para esses parâmetros. Algumas linguagens vão um passo mais longe e permitem-nos definir valores de default nas nossas funções, assim sendo quando chamamos um programa e não fornecemos nenhum valor para os seus parâmetros. o programa assume um dos valores tido como default, isso é uma característica muito forte que existe no Python, e quanto a isso falaremos mais tarde.

No Python a função TABUADA tem esta aparência:

def tabuada(n):
    for i in range(1,13):
        print "%d x %d = %d" % (i, n, i*n)

E é chamada assim:

print "Aqui esta a tabuada do 9..."
times(9)

Nota que estas funções não nos fornecem nenhum valor (elas são na realidade aquilo que algumas linguagens chamam de procedure). Se reparaste a versão do BASIC deste nosso programa usa a palavra-chave SUB em vez de FUNCTION. Sub vem de subroutine, um termo que era bastante usado nos tempos das linguagens de Assembly, e significa que a função especificada não fornecem valores. O Python por sua vez usa o termo def que é o mesmo que 'define', quando esta palavra chave é colocada o interprete assume tudo que vem a segir com parte de uma função que esta a ser criada.

Lembraste certamente que a pouco mencionei o uso de valores default. Um bom uso para estes valores, por exemplo, seria se quiséssemos criar uma função que indicava o dia da semana. Se a chamar-mos sem nenhum valor, ela responderia como sendo hoje. Em caso que quisemos saber qual o dia da semana teríamos que o número do dia como argument. Algo deste género:

# um dia de valor -1 => hoje
def diaDaSemana(DiaNum = -1):
    dias = ['Segunda','Terca',
            'Quarta','Quinta', 
            'Sexta', 'Sabado', 'Domingo']
                
    # verificando pelo valor default        
    if DiaNum == -1:
        # usa o módulo tempo para obter o valor correcto
        # vê a tabela acima e consulta a documentação do Python
        import time
        theTime = time.localtime(time.time())
        DiaNum = theTime[6]
    return dias[DayNum]

Nota: Nós só temos que usar o módulo time (tempo) se o parâmetro de default estiver envolvido, o que significa que não necessitamos de importar o módulo sem que ele seja explicitamente necessário. Isto por certo traria uma certo melhoramento na performance, caso nunca tivéssemos que usar o valores default.

Para ver o módulo em funcionamento:

print "Hoje é: %s" % diaDaSemana()
#lembra-te que em linguagem de computador começamos sempre pelo 0
# e sendo assim e assumindo que o primeiro dia da semana e Segunda.
print "O terceiro dia da semana é%s" % diaDaSemana(2)

De volta a Tabuada de multiplicação...

Então o que aconteceria em caso de querermos definir uma função que simplesmente nos devolvia os valores da multiplicação como um array de número, no BASIC teria este aspecto:

FUNCTION TABUADA% (N%)
    DIM VALORES(12) AS INTEGER
    FOR I = 1 to 12
        VALORES(I) = I*N%
    NEXT I
    RETURN VALORES
END FUNCTION

And in Python:

def tabuada(n):
    # cria uma lista vazia
    valores = []  
    for i in range(1,13):
        valores.append(i*n)
    return valores

Isto na realidade, seria algo bastante inútil, porque muito mais fácil seria fazer a conta a medida que fossemos necessitando dos valores. Mas o que conta é a intenção, e espero que tenhas percebido, o que se estava explicando. Uma função que penso que teria usos muitos mais praticos seria uma que uma que contasse o número de palavras numa string. Depois podias usa-la para contar o número de palavras num ficheiro, para isso bastando que somasses os valores de todas as linhas:

def numpalvras(s):
    lista = split(s) # uma lista em cada elemento da lista é uma palavra
    return len(lista) # devolve o número de elementos pertencentes a lista

for linha in ficheiro:
    total = total + numpalvras(linha) # acumula os totais por cada linha
print "O ficheiro tem %d palavras" % total

Agora em caso que tenhas tentado aplicar este código, de certeza que reparaste que ele não funcionou. O que eu acabei de fazer é uma técnica muito usada na criação de programas, que fazer um skecth de aquilo que eu penso que o código seria mas não verifiquei se ele funcionava na realidade. Digamos que um rascunho. Esta técnica por vezes é conhecida por Pseudocódigo ou em caso que queiram ser mais formais PProgram Description Language) (PDL).

Mais tarde e depois de analisarmos um pouco mais de perto como trabalhar com ficheiros e strings, vamos voltar a este exemplo mas desta vez para o pôr a funcionar correctamente.

Funções no Tcl

É claro que também podemos criar Funções no Tcl, e podemos fazer isso usando o comando proc, assim:

proc tabuada {m} {
    for {set i 1} {$i <= 12} {incr i} {
        lappend resultados [expr $i * $m]
	}
    return $resultados
}

Nota que ao usarmos o comando para criar listas lappend, nós automaticamente criamos uma lista chamada resultados, e a adicionar elementos a essa lista por imediato.

Uma palavras de precaução.

O Tcl é um tanto ou quanto diferente na maneira como lida com as funções. Es capaz de ter notado que eu tenho andado a chamar as funções built-ins de comandos. Isso é porque tudo que se digita na prompt de comando do Tcl é na realidade uma função. A maioria das outras linguagens vêem com um grupo de palavras chaves como, por exemplo for, while, if/else e por aí adiante. O Tcl transforma todas estas palavras chaves em comandos ou funções. Isto pode ter um efeito por vezes muito interessantes, por outras muito confusas, mas sem duvida muito poderosas, pois permitem-nos redefinir e tomar controlo das built-ins. Como neste exemplo que se segue:

set i 3
while {$i < 10} {
    puts $i
    set i [expr $i + 1]
    }

como seria de esperar isto irá imprimir os números de 3 a 9 (menos 1 que 10). Mas agora vamos nós definir a nossa própria versão do comando while:

proc while {x y} {
  puts "O meu while"
}

set i 3
while {$i < 10} {
    puts $i
    set i [expr $i + 1]
    }
    

Isto não irá fazer mais nada senão imprimir a mensagem "o meu While". A expressão e a sequência de comandos são ignorados porque o Tcl os trata como parâmetros da função While, enquanto a função while os ignora. Portanto podes ver como definimos funções no Tcl, e como podemos abusar delas para criar uns programas muito confusos- portanto muito cuidado, não faças alterações a não ser que sejam mesmo necessários!

Criando os nosso próprios módulos

Então, agora podemos criar os nossos próprios módulos e usa-los em qualquer parte dos nossos programas. Isso é muito é muito bom porque pode poupar-nos uma quantidade enorme de trabalho (na parte da dactilografia), principalmente também porque torna os nossos programas mais fácil de interpretar, porque as vezes podemos esquecer alguns detalhes depois de criarmos a função que os esconde (isto é o principio do wrapping, que é esconder as partes mais complexas de um programa dentro de funções, a isto também se pode chamar de information hiding por razões obvias.). Mas agora como podemos estas funções em outros programas que criamos? Para isso nós criamos módulos.

Os módulos do Python

Um módulo no Python, não realmente nada de especial. Na realidade é apenas um ficheiro de texto cheio de comandos de Python Usualmente estes comandos são funções, experimenta:

from sys import *

nós aqui efectivamente, copiamos tudo que estava contido em sys.py para o nosso programa, uma coisa do género copiar e colar (não exactamente isso, mas o conceito é que importa aqui). em algumas linguagens de programação (o C ++ destaca-se aqui das outras) o compilador simplesmente cópia os ficheiros do módulos para dentro do programa a medida que eles vão sendo necessários.

Recapitulando, para criar um módulo no Python é necessário apenas criar um ficheiro de texto contendo os comandos lá dentro e depois de guardado, podemos voltar a reutiliza-lo as vezes que quisermos nos programas que quisermos, parece fácil não é, para dizer a verdade é fácil.

Vamos pôr as mãos a obra e pôr em pratica o que foi acima dito. Copia a função que se apresenta em baixo e guarda o ficheiro com o nome de tabuada.py

def imprime_tabuada(multiplcador):
    print "--- Imprimindo a tabuada do%d ---" % multiplicador
    for n in range(1,13):
        print "%d x %d = %d" % (n, multiplicador, n*multiplicador)

Agora na prompt do Python digita:

>>> import tabuada
>>> tabuada.imprime_tabuada(12)

E vóila, acabaste de criar um módulo e acabaste de o usar.

Nota Importante: Em caso que não tenhas iniciado o Python na mesma directoria onde arquivaste o ficheiro tabuada.py então o Python poderá não encontrar o ficheiro e responderá com uma mensagem de erro. Em caso que isso tenha acontecido podes criar um variável a qual dás o nome de PYTHONPATH, e lá irás guardar uma lista válida de directorias de onde se pode procurar módulos (sem contar com os que vêm com o Python) Criar essas enviroment variables é uma operação especifica de cada plataforma, que eu assumo que saibas fazer ou então consegues descobri como tal se faz.

Módulos em BASIC e no Tcl

Então como ficamos com o BASIC? Bem isso é ligeiramente mais complexo... No QBASIC e noutras versões mais antigas não existe um verdadeiro conceito de módulo. Terás que manualmente cortar e copiar as funções de projectos anteriores para o projecto que estas a trabalhar, e para isso basta um editor de texto. Contudo no Visual Basic já existe um conceito de módulo e podes carregar esse módulo através do Integrated Development Enviroment (IDE) fILE|OPEN MODULE... Existem algumas restrições acerca do que podes fazer dentro de um módulo do BASIC, mas uma vez que isto não é um tutorial acerca do Visual Basic, não vou aprofundar mais sobre o assunto. (Nota: Existem algumas versões do Visual Basic que são conhecidas com COM, estas são versões 'cortadas' por assim dizer, ou seja não têm todas as capacidades incluídas, mas são de graça e podes fazer um download no site da Microsoft, em caso que queiras experimentar, ainda outras versão cortadas que vêem incluídas no Windows 98, 2000 e no IE5, chamados de VBScript e podes usa-las com ficheiros que terminem com .vbs)

Finalmente o Tcl, e como sempre vai exigir muita magia negra e coisas obscuras, mas sem duvida nenhuma muito interessantes no Tcl os módulos são conhecidos como bibliotecas.

A forma mais simples de criar um módulo, é fazer tal qual no Python, e depois quando quiseres inseri-lo no teu programa terás usar esse ficheiro como source. Isto faz que o interprete leia o que esta dentro do ficheiro, e depois aplique no programa que esta a correr, mas existe uma outra opção que não posso deixar de pensar que é muito mais interessante:

Podes criar um ficheiro, tal qual acima, depois de coloca-los numa directoria executas o comando mk_index. Este comando dá-nos uma lista de todas as funções e de todos os ficheiros existentes em determinada directoria. Depois uma vez dentro do teu programa podes simplesmente 'chamar' pela determinada função, uma vez que o interprete do Tcl vai se aperceber que não é uma função built-ins ele irá a lista criada para o procurar. Uma vez encontrada o interprete automaticamente o torna no source e executa a função.

Quando uma dessas funções é utilizada, ela irá ficar disponível, para ser reutilizada em vezes futuras. A única coisa a que se deve prestar muita atenção é não criar ou não ter duas funções com o mesmo nome. Isto no Tcl tem o nome de autoloading.

A seguir iremos dar uma olhadela em como lidar com ficheiros e como lidar com texto, depois como prometido iremos ver de novo a função que serve para contar palavras que estão num ficheiro. Esse módulo irá conter muitas mais capacidades de formas de como lidar com ficheiros.

 
Pontos a lembrar
  • Funções são uma das formas que um módulo pode assumir
  • Funções imprimem ou guardam valores, procedures não.
  • Os módulos do Python normalmente consistem de um ficheiro cheio de comandos do Python
  • Usa a palavra-chave  def para criar novas funções no Python
  • No BASIC deves utilizar SUB ou então FUN, enquanto no Tcl é o proc.

 
Anterior  Índice  Próxima 


m caso que tenhas alguma dúvida ou queiras comentar esta página envia-me um e-mail para: babyboy@oninet.pt