• Nenhum resultado encontrado

ICE-B. 4 - Implementação. Ludwig Krippahl

N/A
N/A
Protected

Academic year: 2021

Share "ICE-B. 4 - Implementação. Ludwig Krippahl"

Copied!
37
0
0

Texto

(1)

ICE-B

4 - Implementação

(2)

Implementação

Resumo

■ Exemplo: cálculo de pH, agora estruturado

■ Testes unitários

■ Ciclo de vida de um programa

(3)

Implementação

(4)

Calcular pH

Solução de ácido benzóico

C H COOH H + C H COO6 5 ⇔ + 6 5

■ Constante de dissociação,

■ Ignorando auto-dissociação da água:

■ Resolvemos equação quadrática,

• (só precisamos da solução positiva)

■ Depois calculamos o pH:

= 6.5 ×

K

a

10

−5 = = ⇔ + x − = 0 Ka [H ][ CO ] + C 6H5 O− [C6H5COOH] x2 − x Ci x 2 K a CiKa

x =

−b±2ab2−4ac pH = −lo ([g10 H+]) = −lo (x)g10

(5)

Calcular pH

Compreender, generalizar e decompor

■ Generalização: Calcular o pH de um ácido fraco monoprótico

■ Decomposição: Obter a raíz positiva e calcular o pH

■ Criamos ficheiro phcalc.py com o "esqueleto" do programa

# coding: utf-8

-*-"""

Computes pH of an acid from concentration """

def positive_root(a, b, c):

"return positive root of quadratic equation"

def compute_pH(Ka, Ci):

"""

return pH value for weak acid from

dissociation constant and initial concentration """

(6)

Calcular pH

"Esqueleto" do programa

■ É uma boa ideia fazer primeiro um esboço do programa

• Permite ver se encaixa tudo e se é preciso decompor mais

■ Estas funções ainda não fazem nada mas este código já cria os objectos.

def positive_root(a, b, c):

"return positive root of quadratic equation"

■ A string logo a seguir à assinatura é a documentação

• Podem usar ''' ou """ se o texto ocupar várias linhas In : help(positive_root)

Help on function positive_root in module __main__: positive_root(a, b, c)

(7)

Calcular pH

Documentação do módulo

■ A string no início do módulo é útil como documentação

# coding: utf-8

-*-"""

Computes pH of an acid from concentration """

■ Depois de executar com F5, podemos importá-lo e pedir ajuda In : import phcalc

In : help(phcalc)

Help on module phcalc: NAME

phcalc - Computes pH of an acid from concentration FUNCTIONS

compute_pH(Ka, Ci)

(8)

Calcular pH

Implementar as funções

■ Depois de perceber os objectivos e o algoritmo e de decompor em tarefas podemos implementar cada função

■ Devemos começar pelas "pontas", aquelas que não dependem de nenhuma outra que tenhamos de implementar

def positive_root(a, b, c):

"return positive root of quadratic equation" root = (-b + (b**2 - 4*a*c)**0.5)/(2*a)

return root

■ Depois devemos testar:

In : positive_root(1,0,-1) #x**2 + 0x - 1

Out: 1.0

In : positive_root(1,-2,0) #x**2 - 2x + 0

(9)

Calcular pH

Implementar as funções

Depois de implementar e testar uma função podemos passar a outra que dependa desta

■ Como o cálculo do pH precisa do logaritmo, temos de importar log10

• É melhor fazer todos os import no início do módulo

# coding: utf-8

-*-"""

Computes pH of an acid from concentration """

from numpy import log10

def positive_root(a, b, c):

...

(10)

Calcular pH

Implementar as funções

■ Agora implementamos e testamos esta também

def compute_pH(Ka, Ci):

"""

return pH value for weak acid from

dissociation constant and initial concentration """

H = positive_root(1, Ka, -Ka*Ci) return -log10(H)

■ Testar com valores que permitam confirmar o resultado: In : compute_pH(6.5e-5,0.01)

(11)

Testes Unitários

Testar sempre cada função

■ Decompomos um problema complexo em problemas mais simples.

■ Mas depois vai ser preciso juntar tudo.

• Um erro descoberto só no final é mais difícil de encontrar e corrigir.

■ É preciso testar:

• Sempre que implementamos algo de novo.

• Sempre que corrigimos um erro, para confirmar.

(12)

Testes Unitários

Sugestão: automatizar os testes todos

■ Opção 1: uma função no final do nosso módulo

• Numa função para não correr os testes sempre que usamos o módulo ...

def tests():

"""

run unit tests on all functions """

print("positive_root, 1.0:", positive_root(1,0,-1)) print("positive_root, 2.0:",positive_root(1,-2,0)) print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01))

■ É importante que se possa verificar o resultado também In : tests()

positive_root, 1.0: 1.0

positive_root, 2.0: 2.0

(13)

Testes Unitários

Sugestão: automatizar os testes todos

■ Opção 2: um módulo só para testes (phtests.py)

# coding: utf-8

-*-"""

run unit tests on all functions in phcalc """

from phcalc import positive_root, compute_pH

print("positive_root, 1.0:", positive_root(1,0,-1)) print("positive_root, 2.0:",positive_root(1,-2,0)) print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01))

■ Basta correr com F5

• Neste caso não é preciso função porque o módulo é só para testes In : runfile('/pasta/phtests.py', wdir='/pasta')

(14)

Testes Unitários

Atenção: funções são criadas na execução do def...

def tests():

"""

run unit tests on all functions """

print("positive_root, 1.0:", positive_root(1,0,-1)) print("positive_root, 2.0:",positive_root(1,-2,0)) print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01))

■ Sempre que alterarem alguma coisa no vosso programa precisam de criar novamente os objectos das funções alteradas

■ Para isso o interpretador tem de reler a assinatura da função e toda a "receita" no corpo da função

■ A forma mais prática de fazer isso no Spyder é F5

• (Grava e corre todo o ficheiro)

(15)

Testes Unitários

Atenção: funções são executadas só em nome( ... )

In : tests()

positive_root, 1.0: 1.0

positive_root, 2.0: 2.0

compute_pH, 3.111: 3.11104555393

■ Quando se corre módulo as funções são criadas mas não usadas

■ A menos que o módulo inclua também chamadas às funções

# coding: utf-8

-*-...

def tests():

print("positive_root, 1.0:", positive_root(1,0,-1)) print("positive_root, 2.0:",positive_root(1,-2,0)) print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01)) tests()

(16)

Testes Unitários

Atenção: função só devolve valor em return

# coding: utf-8

-*-...

def tests():

print("positive_root, 1.0:", positive_root(1,0,-1)) print("positive_root, 2.0:",positive_root(1,-2,0)) print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01))

In : tests()

positive_root, 1.0: 1.0

positive_root, 2.0: 2.0

compute_pH, 3.111: 3.11104555393

■ O print escreve na consola mas a função tests() não devolveu valor (devolveu None).

(17)

Programação Estruturada

(18)

Erros

Erro de sintaxe

■ Erro na escrita do código que impede o interpretador de o executar

• Este é o mais fácil de corrigir, porque sabemos logo que o cometemos In : 6 * * 2

6 * * 2

^

SyntaxError: invalid syntax In : 8 + 5.3.2

8 + 5.3.2

^

SyntaxError: invalid syntax

■ Spyder analisa o código conforme o escrevemos e assinala a linha com o erro

(19)

Erros

Erro de execução (Exception)

■ O interpretador sabe o que deve fazer mas não consegue fazê-lo

• Estes erros só ocorrem durante a execução e podem ser mais difíceis de diagnosticar porque o erro pode estar noutra parte do código

In : y = z*2

y = z*2

NameError: name 'z' is not defined In : y = 0

In : z = 1 / y z = 1 / y

(20)

Erros

Erro lógico

■ O programa corre sem problemas mas não dá o resultado certo

• Estes erros tendem a ser os mais difíceis de corrigir

■ Exemplo: pH negativo?

def positive_root(a, b, c):

root = (-b + (b**2 - 4*a*c)**0.5)/(2*a) return root

def compute_pH(Ka, Ci):

H = positive_root(1, Ka, -Ka*Ci) return log10(H)

In : compute_pH(6.5e-5,0.01) Out: -3.11104555393015

(21)

Erros

Erro numérico

■ Devido à representação finita de números fraccionários, em 64 bits

• (Inteiros em Python 3.x usam o número de bits que for necessário)

• Obriga a arredondamentos e pode ser importante se o cálculo for iterado In : (2**0.5)**2

Out: 2.0000000000000004

■ Representação de números fraccionários em 64 bits:

• 1 bit para sinal, 11 para expoente (base 2) e 52 para fracção

(22)

Erros

Erro numérico

■ Informação sobre a representação em 64 bits In : import numpy In : info = numpy.finfo(float) In : info.bits Out: 64 In : info.eps Out: 2.2204460492503131e-16 In : info.tiny Out: 2.2250738585072014e-308 In : info.min Out: -1.7976931348623157e+308 In : info.max Out: 1.7976931348623157e+308 Informação:

Número de bits na representação Menor valor que somado a 1 dá >1

In : 1+info.eps-1

Out: 2.2204460492503131e-16

In : 1+0.5*info.eps-1

Out: 0.0

Mais pequeno com plena precisão

Menor valor representável

(23)

Programação Estruturada

(24)

Ciclo de vida

Ciclo de vida de um programa

■ Edição do código fonte

• Escrito, guardado em ficheiros .py

■ Interpretação do código fonte

• O interpretador traduz as instruções em instruções para o CPU

■ Execução

• O CPU executa o programa

■ Testar e avaliar o resultado

(25)

Ciclo de vida

Ciclo de vida de um programa, exemplo

■ Concebemos, implementámos e testámos o cálculo do pH

• A partir da concentração inicial e da constante de dissociação

Agora temos um novo problema

■ Qual o pH de 0.01g de ácido benzóico em 0.250 dm ?

• Calcular pH a partir da massa, volume e massa molecular

• Basta calcular a concentração e usar o que já temos

■ Solução: acrescentamos uma nova função

• Pensamos no algoritmo: calcular concentração

• Decompomos se necessário (não é; é simples)

• Implementamos e testamos

(26)

Ciclo de vida

Novo problema:

■ Qual o pH de 0.01g de ácido benzóico em 0.250 dm ?3

Solução:

■ Já temos praticamente tudo feito

■ Basta uma função que calcule a concentração

• Precisa da massa, massa molar e volume

■ E depois chamar a anterior com concentração e

K

a

def compute_pH_mass(mass, mol_mass, volume, Ka):

"""

return pH value of a weak acid solution from mass of solute and volume of solution

"""

Ci = mass / mol_mass / volume return compute_pH(Ka,Ci)

(27)

Ciclo de vida

■ Uma maneira prática é acrescentar ao módulo phcalc

# coding: utf-8

-*-"""

Computes pH of an acid from concentration """

from numpy import log10

def positive_root(a, b, c):

...

def compute_pH(Ka, Ci):

...

def compute_pH_mass(mass, mol_mass, volume, Ka):

"""

return pH value of a weak acid solution from mass of solute and volume of solution

"""

Ci = mass / mol_mass / volume return compute_pH(Ka,Ci)

(28)

Ciclo de vida

Ciclo de vida de um programa, exemplo

■ Calcular o pH a partir da massa, volume e massa molecular:

def compute_pH_mass(mass, mol_mass, volume, Ka):

"""

return pH value of a weak acid solution from mass of solute and volume of solution

"""

Ci = mass / mol_mass / volume return compute_pH(Ka,Ci)

■ Testes:

def tests():

...

print("compute_pH, 3.111:",compute_pH(6.5e-5,0.01))

print("compute_pH_mass, 3.1111",compute_pH_mass(1.221, 122.1, 1, 6.5e-5)) print("compute_pH_mass, 3.000",compute_pH_mass(0.5, 122.1, 0.25, 6.5e-5))

(29)

Implementação

(30)

Estilo de Código

É importante escrever código legivel

■ Porque o código fonte serve:

• Para o interpretador executar

• Para humanos lerem

■ Código difícil de compreender

• É mais propenso a erros

• É mais difícil de corrigir, adaptar e melhorar

(31)

Estilo de Código

Nomes de variáveis

■ As variáveis devem ter nomes descritivos

• E.g. mass, mol_mass, volume

def compute_pH_mass(mass, mol_mass, volume, Ka):

Ci = mass / mol_mass / volume return compute_pH(Ka,Ci)

■ Excepto quando têm nomes convencionais

• E.g. a, b, c, Ci, pH, Ka

def positive_root(a, b, c):

root = (-b + (b**2 - 4*a*c)**0.5)/(2*a) return root

(32)

Estilo de Código

Nomes de funções

■ Devem descrever o que a função faz

■ Nomes compostos por várias palavras

• Convenção 1: usar letras maiúsculas e minúsculas phMassVol

• Convenção 2: (mais usado em Python) usar underscore compute_pH_mass

def compute_pH_mass(mass, mol_mass, volume, Ka):

Ci = mass / mol_mass / volume return compute_pH(Ka,Ci)

(33)

Estilo de Código

Inteligibilidade

■ Cada linha de código deve corresponder a um passo simples

■ Evitar linhas demasiado longas ou complexas

• Decompor em vários passos para ser mais inteligivel

■ Exemplo: menos claro

def compute_pH_mass(mass, mol_mass, volume, Ka):

return compute_pH(Ka, mass / mol_mass / volume)

■ Exemplo: mais claro

def compute_pH_mass(mass, mol_mass, volume, Ka):

Ci = mass / mol_mass / volume return compute_pH(Ka, Ci)

(34)

Estilo de Código

Documentação e comentários

■ Devemos documentar funções (e módulos)

■ Podemos também acrescentar comentários se for preciso

• Notas para o programador

def positive_root(a, b, c):

"return positive root of quadratic equation"

root = (-b + (b**2 - 4*a*c)**0.5)/(2*a) #This assumes a is greater than zero

return root

Mais informação:

■ https://www.python.org/dev/peps/pep-0008/ "PEP 8 -- Style Guide for Python Code"

(35)

Programação Estruturada

(36)

Implementação

Resumo

■ Programação estruturada: funções

■ Testes unitários

■ Tipos de erro: sintaxe, exception, lógicos e numéricos

■ Ciclo de vida e reutilização de código

■ Estilo de código

Leitura adicional:

■ Recomendada: Capítulo 4 dos apontamentos

(37)

Referências

Documentos relacionados

À Família Caridade e Firmeza: ao ser escolhido para dirigir a Loja Ca- ridade e Firmeza, mais que centená- ria, Cruz da Perfeição Maçônica, em seu jubileu de Prata, que no dia 02

Os quatro objetos propostos aqui serão posteriormente observados a olho nu e com o auxílio do binóculo, para que possamos mostrar o quanto esse aparelho é uma poderosa ferramenta

Esta base contém as informações de abordagens de marketing para pessoas que já são clientes e para pessoas que ainda não são clientes de uma instituição financeira, como:

Neste sentido, para os efeitos da presente matéria, a legislação nacional, em particular, a Constituição da República e a Lei do Trabalho, garantem que todos os

Na análise de currículo serão considerados apenas itens da Ficha de Avaliação do Currículo do candidato que sejam efetivamente comprovados e pertinentes à área de

Evento que exigiu o fim da impunidade para os Crimes de Maio de 2006 reuniu vítimas da violência policial de vários Estados e deixou claro que os massacres de pobres e jovens

Tendo em vista todo contexto positivo que as aulas práticas laboratoriais causam no processo de aprendizagem e das muitas dificuldades encontradas para suas

mas, caso não se sinta preparado, nem tente fazer isso...o nosso corpo astral sente de maneira muito mais intensa preparado, nem tente fazer isso...o nosso corpo astral sente de