Baixe o app para aproveitar ainda mais
Prévia do material em texto
Disciplina: Informática para Engenharia Aula 5: Modularização Apresentação Os principais desafios para programadores estão relacionados com a construção de softwares de qualidade. É altamente desejável a construção de programas legíveis e de fácil manutenção. A divisão do programa em módulos, ou subprogramas, evita a duplicação de código e de responsabilidades, tendo impactos diretos para a boa manutenção do software. Essa estratégia auxilia (e muito) na resolução de problemas grandes e complexos. Um dos produtos obtidos pela aplicação de técnicas de modularização consiste na construção de bibliotecas. A criação de rotinas em arquivos específicos possibilita o seu reuso em futuras implementações. Objetivos Formular programas com base em técnicas de modularização; Construir programas e bibliotecas reusáveis em Python segundo os conceitos da programação modular. Modularização de Programas Até o momento, construímos algoritmos que executam de uma forma puramente sequencial. Imagine se você precisasse calcular a média final de um aluno para saber se ele foi aprovado, reprovado ou se foi para a final. A solução é simples nesse caso, pois precisaremos realizar o cálculo somente uma vez. Agora suponha que quiséssemos fazer o mesmo cálculo, mas para uma turma de 30 alunos. Bem, será que agora teremos de escrever a mesma equação 30 vezes? # Dados para o 1 aluno >>> nota_prova1 = input(‘Informe a nota da prova 1’) >>> nota_prova2 = input(‘Informe a nota da prova 2’) >>> media = (nota_prova1 + nota_prova2) / 2 # Dados para o 2 aluno >>> nota_prova1 = input(‘Informe a nota da prova 1’) >>> nota_prova2 = input(‘Informe a nota da prova 2’) >>> media = (nota_prova1 + nota_prova2) / 2 # e assim por diante, até o 30 aluno… Podemos observar dois problemas na construção do algoritmo proposto. O primeiro está relacionado à repetição das leituras das variáveis nota_prova1 e nota_prova2, além do cálculo para a média, que nunca muda! Eis que surge uma questão: não poderíamos criar um módulo responsável por somente calcular a média? Nesse caso, só chamaremos a função já codificado passando as notas e tendo como retorno a situação do aluno (aprovado, reprovado ou em prova final). Esse é o mais simples conceito de modularização. Para o referido exemplo, poderíamos pensar em algo do tipo: o o o Pseudocódigo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Algoritmo calcula_media nota_prova1, nota_prova2: real início escreva(‘Digite a nota1: ‘) leia(nota_prova1) escreva(‘Digite a nota2: ‘) leia(nota_prova2) media:=calcula_media(nota_prova1,nota_prova2) escreva(media) fim funcao calcula_media(real nota1, real nota2) inicio retorna (nota1 + nota2) /2 fim. Python 1 2 3 4 5 6 def calcula_media(nota1, nota2): return ((nota1+nota2)/2) nota_prova1=float(input('Digite a nota1: ')) nota_prova2=float(input('Digite a nota2: ')) media=calcula_media(nota_prova1, nota_prova2) 7 8 9 10 11 12 13 14 15 print(media) Outro ponto positivo reside no fato de que queremos somente calcular a média, não nos importando como isso é feito. Observe no pseudocódigo que, se mudarmos a forma de cálculo na função calcula_ media, não precisaremos alterar nenhuma instrução no algoritmo principal. Ou seja, a manutenção só é realizada em um único ponto de todo o código. No entanto, ainda não resolvemos o problema da leitura repetida dos 30 alunos, correto? Mas, analisando novamente o pseudocódigo, podemos perceber que as instruções da linha 4 até a linha 10 seriam as mesmas para os 30 alunos. Logo, poderíamos criar mecanismos para repetir esse código do 1 até o 30 aluno. No entanto, esse é um assunto que será abordado nas próximas aulas. Blocos de Código o o Analisando mais uma vez o pseudocódigo, podemos ver duas estruturas distintas, delimitadas pelas palavras reservadas início e fim: o conjunto de ações do algoritmo principal e o outro da função calcula_media. Esses são dois exemplos de blocos. Um bloco pode ser definido como um conjunto de ações com uma função definida. Nesse caso, um algoritmo pode ser visto como um bloco. Para melhor ilustrar o conceito de blocos, vamos considerar um exemplo um pouco mais complexo, que envolve a ordenação de dados contidos em uma lista. Podemos perceber no exemplo que o uso dessa abordagem torna o algoritmo principal (Algoritmo OrdenaPorSeleção) mais compreensível e abre a possibilidade de chamar a mesma rotina (Algoritmo EncontraMenor) em outras partes do programa sem reescrevê-lo. Funções Função é uma sequência de instruções que executa algum tipo de tarefa. Usamos funções para eliminar a duplicação de código. Em vez de escrevermos todas as instruções em todos os lugares em nosso código onde queremos executar a mesma tarefa, nós os definimos em um lugar e nos referimos a eles pelo nome da função. Se quisermos mudar a forma como essa tarefa é executada, agora só precisaremos alterar o código em um só lugar. Em programação estruturada, um pequeno detalhe diferencia um procedimento de uma função: a 1 não retorna valor, enquanto a 2 sempre retorna. Outra questão é que uma função deve ter pelo menos um argumento. A seguir, é mostrado um código para cálculo de juros de determinada quantia informada pelo usuário. Observe os elementos da função. Uma característica do Python é que os parâmetros, também conhecidos por argumentos, podem ter um valor-padrão caso esse seja omitido na chamada da função. Observe o código. a a O que aconteceria se não informássemos a quantia (linha 11) para a função calcula_juros (linha 7)? O programa nos retornaria o valor 2.3, já que, na omissão da quantia na chamada da função (linha 11), o argumento valor (linha 7) recebe, por padrão,10! Escopo de Variáveis Nem todas as variáveis são acessíveis de todas as partes do nosso programa. Além disso, nem todas elas existem pelo mesmo período de tempo. A acessibilidade do local de uma variável e o tempo dela dependem de como essa variável é definida. Chamamos de escopo a parte de um programa onde uma variável é acessível e a duração para a qual ela existe em seu tempo de vida. Uma variável definida no corpo principal de um arquivo é chamada de variável global. Ela será visível em todo o arquivo e também dentro de qualquer arquivo que importe esse arquivo. 1 2 3 4 5 6 7 8 9 10 11 # -*- coding: utf-8 -*- ″″″ Algoritmo: Cálculo de juros Entrada: quantia informada pelo usuário Saída: juros calculados ″″″ def calcula_juros(valor): taxa=0.23 return (valor*taxa) quantia=float(input(″Digite uma quantia para o cálculo dos juros″)) 12 13 juros = calcula_juros(quantia) print(juros) As linhas 11 e 12 ilustram as variáveis globais do programa. Nesse, caso elas podem ser acessadas dentro da função da linha 7. Já a taxa (linha 8) é uma variável local da função calcula_juros. Dessa forma, ela não é acessada/visualizada fora da função. Um artifício para referenciar uma variável global em um contexto local (uma função, por exemplo) seria usar a palavra reservada global associada à variável desejada. Uma variável definida dentro de uma função é local para essa função. Chamada de variável local, é acessível a partir do ponto em que é definida até o final da função e existe enquanto a função estiver sendo executada. Sabendo disso, o que aconteceria se quiséssemos imprimir a variável taxa (linha 14) conforme o código a seguir? 1 2 3 4 5 6 7 8 9 10 11 12 13 # -*- coding: utf-8 -*- ″″″ Algoritmo: Cálculo de juros Entrada: quantia informada pelo usuário Saída: juros calculados ″″″ def calcula_juros(valor): taxa=0.23 return (valor*taxa) quantia=float(input(″Digite uma quantia para o cálculo dos juros″)) juros = calcula_juros(quantia) print(juros) 14 print(taxa) O Python nos daria a seguinte mensagem: “NameError: name 'taxa' is not defined”. Ou seja, para o programa principal, a variável taxa não está definida. Os nomes dos parâmetros na definição da função se comportam como variáveis locais, mas contêmos valores que passamos para a função quando a chamamos. Tomando como exemplo o código anterior, o parâmetro valor (linha 7) só é visível dentro da função. Modularizando o Código Todos os projetos de software começam pequenos, e é provável que você comece escrevendo todo o código do seu programa em um único arquivo. À medida que seu projeto cresce, torna-se cada vez mais inconveniente fazer isso. É difícil encontrar algo em um único arquivo de código, e, com o tempo, é provável que você encontre um problema se quiser chamar duas classes diferentes com o mesmo nome. Em algum momento, será uma boa ideia arrumar o projeto dividindo-o em vários arquivos, colocando classes ou funções relacionadas juntas no mesmo arquivo. Exemplo Por exemplo, podemos construir dois módulos em Python para lidar com aspectos financeiros e administrativos (arquivos financeiro.py e admin.py, respectivamente). Assim, podemos utilizar as funções desses arquivos simplesmente importando-os para o programa principal. A figura apresenta três pacotes distintos. O ordenacao.py tem uma coleção de funções para ordenar listas. Já o format.py possui uma série de métodos relacionados com o tratamento de strings, assim como o pacote io.py. Com o tempo, os nossos módulos podem ficar maiores, ou seja, com uma grande quantidade de funções em um único arquivo. Mais uma vez, podemos agrupar os módulos de acordo com o propósito em pacotes! De forma resumida, pacote é um diretório (ou pasta) que contém um arquivo chamado __init__.py. A importação é bem parecida com um módulo e necessita que usemos o nome do diretório. Automaticamente, todos os módulos são importados para o código que invocou. De acordo com o exemplo anterior, imagine se quiséssemos criar um pacote para formatar números inteiros. Poderia ser uma boa ideia a inclusão de mais funções no arquivo format.py, ok? No entanto, estaríamos misturando funções que manipulam string com números. Uma boa solução seria a criação de pacotes para string e números! A figura a seguir exibe a estrutura de pastas após a organização dos pacotes em módulos. Agora podemos ter um módulo com mesmo nome, isto é, format.py na pasta number e outro arquivo format.py na pasta string. Note que assim agrupamos os arquivos em função de suas características. Esse é bom um exemplo de organização de código! Teste o seguinte código no terminal ou no seu IDE preferido. Após criar a estrutura, digite o conteúdo a seguir no arquivo format.py do diretório number. # -*- coding: utf-8 -*- #format.py def abs(arg1): return "retorna valor absoluto" def to_str(arg1): return "formatação para string" A seguir, o código do arquivo main.py. # -*- coding: utf-8 -*- #main.py from number import format print(format.abs(0)) No caso de existirem nomes de pacotes duplicados, podemos criar um alias (apelido) através da diretiva as. Por exemplo, suponha que tenhamos pacotes conversores.py em pastas distintas. Apesar do mesmo nome, poderíamos importá-los da seguinte maneira: from pacoteX import conversores as cvs1 from pacoteY import conversores as cvs2 Atividade 1. Observe o código a seguir: def my_function (a): b = a - 2 return b c = 3 if (c > 2): d = my_function(5) print(d) (a) Descreva o escopo das variáveis a, b, c e d neste exemplo. (b) Qual é o tempo de vida dessas variáveis, ou seja, quando elas serão criadas e destruídas? (c) Você consegue adivinhar o que aconteceria se tivéssemos atribuído ao c um valor de 1? 2. Qual é a saída do programa a seguir? x = 50 def func(): global x print('x é', x) x = 2 print('Alterada a variável global x para', x) func() print('O valor de x é ', x) a) x é 50; alterada variável global x para 2; O valor de x é 50. b) x é 50; alterada variável global x para 2; O valor de x é 2. c) x é 50; alterada variável global x para 50; O valor de x é 50. d) Nenhuma das mencionadas. 3. Sobre o último exemplo de criação de pacotes e módulos, implemente uma simples função no arquivo format.py no pacote string. Essa função, chamada de “para_moeda”, deve receber um argumento e retornar a mensagem “A conversão efetuada foi ” mais o argumento passado. No módulo main.py, importe e invoque o referido método. Referências GRUS, J. Data science from scratch: first principles with Python. Beijing: O’Reilly, 2015. MENEZES, N. N. C. Introdução à programação com Python: algoritmos e lógica de programação para iniciantes. 1. ed. São Paulo: Novatec, 2017. MUELLER, J. P. Começando a programar em Python para leigos. Alta Books, 2016. PERKOVIC, L. Introduction to computing using Python: an application development focus. 2. ed. [s.l.] Wiley Publishing, 2015. Próximos Passos Apresentar técnicas para a resolução de problemas que envolvem tomada de decisão; Analisar o uso das relações lógicas e aritméticas para a construção de estruturas de decisão; Ilustrar os conceitos relacionados a estruturas condicionais simples e compostas. Explore mais Leia o texto: Módulos e Pacotes <https://wiki.python.org.br/ModulosPacotes> . Assista aos vídeos: “Pacotes em Python <https://www.youtube.com/watch? v=StKzd2331X4> ”. “Utilizando Módulos <https://www.youtube.com/watch? v=oOUyhGNib2Q> ”. https://wiki.python.org.br/ModulosPacotes https://www.youtube.com/watch?v=StKzd2331X4 https://www.youtube.com/watch?v=oOUyhGNib2Q
Compartilhar