Informá(ca para as Ciências e Engenharias
Versão : B
(Lic.Biologia Celular e Molecular
MI Engenharia Química e Bioquímica)
Aula 8
Pedro Barahona 2020 / 21
Sumário
• Dados estruturados. Dicionários.
• Vetores e dicionários de dicionários.
• Outras u9lizações de dicionários.
Sumário
• Dados estruturados. Dicionários.
• Vetores e dicionários de dicionários. • Outras u9lizações de dicionários. • Resolução de problema
Dados Estruturados - Dicionários
• Por vezes, pretende-se agrupar um conjunto de dados relacionados, acedendo aos dados através dum nome.
Exemplo: Para cada elemento da tabela periódica pode ser associado: § O símbolo químico (que é uma string) ao nome simboloQ;
§ O número atómico (um inteiro) ao nome numAtom.
• Em Python, podem-se agrupar dados relacionados num Gpo de dados chamado dicionário (Gpo dict). Um dicionário é um conjunto de pares chave/valor.
§ A chave pode ser uma string, inteiro, float ou booleano. § O valor pode ser de qualquer Gpo.
Dicionários - Criação
• Em Python um dicionário, é um objeto do Gpo dict, criado com a seguinte
Sintaxe:
variavel = { nomeDaChave1 : valorDaChave1, .... nomeDaChaveN : valorDaChaveN } • Exemplo: In : actínio = { ...: 'simbQ' : 'Ac’, ...: 'nAtom' : 89} In : actínio
Dicionários – Valores das Chaves
• Os valores das chaves de um dicionário podem ser acedidos (e alterados, usando o método .get (ou a sintaxe equivalente):
variável.get(NomeDaChave)
ou pela sintaxe equivalente
variável[NomeDaChave] In : lítio = { ...: 'simbQ' : 'Li', ...: 'nAtom' : None} In : lítio['nAtom'] In : lítio['nAtom’] = 3 In : lítio['nAtom'] Out: 3 In : lítio.get(‘simbQ’) Out: 'Li' In : lítio
Dicionários – Adição de Chaves
• Uma vez criado um dicionário, podem ser acrescentados pares chave/valor através do método .update
variável.update(NomeDaChave) Exemplo:
• Acrescentar a massa atómica à descrição de um átomo. In : lítio
Out: {'simbQ': 'Li', 'nAtom': 3}
In : lítio.update({'massAtom': 6.941}) In : lítio
Dicionários – Eliminação de Chaves
• Igualmente podem ser eliminados pares chave/valor de um dicionário através do método .pop
variável.pop(NomeDaChave) Exemplo:
• Eliminar a massa atómica à descrição de um átomo. In : lítio
Out: {‘simbQ': 'Li', 'nAtom': 3, 'massAtom': 6.941} In : lítio.pop('massAtom')
Out: 6.941 In : lítio
Dicionários – Que Chaves?
• Para se saberem que chaves existem num dicionário, pode ser usado o método .keys.
variável.keys()
• Que pode ser usado para verificar se uma dada chave existe chave in variavel.keys()
Exemplo:
• Atributos associados a um elemento químico In : lítio = { ...: 'simbQ' : 'Li', ...: 'nAtom' : None} In : lítio.keys() In : dict_keys(['simbQ', 'nAtom’]) In : 'nAtom’ in lítio.keys() Out: True
Dicionários – Iteração por Chaves
• As vários atributos de um dicionário podem ser iterados (por exemplo, numa instrução FOR) acdendo às suas chaves :
for chave in variável.Keys()
ou com a sintaxe simplificada:
for chave in variável
• Exemplo:
In : lítio
Out: {'simbQ': 'Li', 'nAtom': 3} In : for chave in lítio.Keys(): ...: print(chave)
simbQ nAtom
In : for chave in lítio: ...: print(chave)
simbQ nAtom
Sumário
• Dados estruturados. Dicionários.
• Vetores e dicionários de dicionários.
• Outras u9lizações de dicionários. • Resolução de problema
Vetores de Dicionários
• Dicionários podem ser organizados em listas (implementando vetores
ou matrizes).
Exemplo:
• Elementos da Tabela Periódica (incompleta) In : lítio
Out: {'simbQ': 'Li', 'nAtom': 3} In : actínio
Out: {'simbQ': 'Ac', 'nAtom': 89} In : elems = [lítio, actínio]
In : elems[0]
Out: {'simbQ': 'Li', 'nAtom': 3} In : elems[1].get('nAtom’)
Out: 89
In : elems[1][nAtom] Out: 89
Dicionários de Dicionários [1]
• Para facilitar a acessibilidade aos seus elementos, podem ser organizados em outros dicionários
Exemplo:
• Elementos da Tabela Periódica indexados por número atómico In : litio
Out: {‘simbQ': 'Li', 'nAtom': 3} In : actínio
Out: {‘simbQ': 'Ac', 'nAtom': 89} In : tabela = {}
In : tabela[3] = lítio In : tabela[89] = actínio In : tabela
Out: {3:{‘simbQ':'Li’, 'nAtom': 3}, 89:{‘simbQ': 'Ac', 'nAtom': 89}} In : tabela[89]
Out: {‘simbQ': 'Ac', 'nAtom': 89} Out: 89
Dicionários de Dicionários [2]
• Os dicionários podem ser indexados de várias maneiras (por exemplo número atómico e símbolo químico
In : tabela
Out: {3:{‘simbQ':'Li’, 'nAtom': 3}, 89:{‘simbQ': 'Ac', 'nAtom': 89}} In : tabela['Li'] = litio
In : tabela['Ac'] = actinio In : tabela['Li']
Out: {'simbQ':'Li', 'nAtom': 3}, In : tabela[89]
Out: :{'simbQ': 'Ac', 'nAtom': 89}} In : tabela
Out: {3:{'simbQ':'Li’, 'nAtom': 3}, 89:{'simbQ': 'Ac', 'nAtom': 89}, ‘Li’:{'simbQ':'Li’, 'nAtom': 3}, ‘Ac’:{'simbQ': 'Ac', 'nAtom': 89}}
Sumário
• Dados estruturados. Dicionários. • Vetores e dicionários de dicionários.
• Resolução de problemas
§ Frequências / Histogramas
Problema – Frequência de letras
• Dicionários podem ser uGlizados numa variedade de aplicações. Começamos pelo seguinte problema (com aplicações aos protocolos de transmissão de informação):
• Problema: Qual a frequência com que aparecem as várias letras num
texto? Mais especificamente:
Resolução – Problema [1]
1. Compreender totalmente o problema.
§ O problema é claro.
2. Caracterizar o problema.
• Problema: Frequência de letras.
• Entrada: (string) nomeFich.
• Saída: dicionário com pares (string)letra: (int) que indicam o número de vezes que a letra aparece no texto.
Nota: Não distinguiremos letras maiúsculas de minúsculas
3. Generalizar o problema (sempre que for possível).
Resolução – Algoritmo [1]
4. Desenhar o algoritmo para resolver o problema.
a) Conceber o algoritmo, decompondo o problema em sub-problemas. Podemos decompor este problema em 3 sub-problemas
1. Ler o ficheiro indicado
• Ler um ficheiro para uma string
2. Contar a ocorrência das letras numa string
• Criar um Dicionário com pares letra: contagem
3. Integrar os dois problemas anteriores
• Ler o ficheiro para um texto
Resolução – Algoritmo [2]
b) Iden9ficar, caracterizar e generalizar cada sub-problema. [1]
• Problema: Leitura do Ficheiro de texto. • Entrada: (string) nomeFich.
• Saída: (string) texto lido
Um problema semelhante a este foi resolvido na aula anterior b) Iden9ficar, caracterizar e generalizar cada sub-problema. [2]
• Problema: Contar as letras de um texto. • Entrada: (string) texto.
• Saída: (dict) conjunto de pares letra:contagem
Um problema semelhante a este foi resolvido na aula anterior b) Iden9ficar, caracterizar e generalizar cada sub-problema. [3]
Resolução – Algoritmo [2]
5. Para cada sub-problema, desenhar o algoritmo para o resolver.
Sub-problema: Leitura do Ficheiro de texto
1. Abrir o ficheiro para leitura.
2. Ler todos os caracteres.
Resolução – Algoritmo [3]
5. Para cada sub-problema, desenhar o algoritmo para o resolver.
Sub-problema: Contar as letras de um texto
1. Criar um dicionário vazio.
2. Para todos os caracteres alfanuméricos.
• Convertê-los para minúsculas
• Se o caracter já existe no dicionário :
§ incrementar a sua contagem
• Caso contrário
§ Criar uma entrada com contagem 1
Resolução – Implementação [1]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Sub-problema: Leitura do Ficheiro de texto
def leFicheiro(nomeFich): """ ... """ fich = open( nomeFich, "w") texto = fich.read() fich.close() return texto
Resolução – Implementação [2]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Sub-problema: Contar as letras de um texto
def contagem(texto):
""" ... """
hist = {}
for ch in texto: ch = ch.lower()
if ch.isalpha() and ( ch in hist.keys() ): hist[ch] = hist[ch] + 1
elif ch.isalpha():
hist.update({ch: 1})
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Sub-problema: Integrar as funções anteriores
• Este programa pode ser testado com qualquer ficheiro texto.
• (deve ser testado com poucos caracteres para se poder verificar se
a contagem está correta). def histograma(nomeFich):
""" ... """
texto = leTexto(nomeFich) hist = contagem(texto)
Resolução – Teste
In : hist = d.histograma('texto_teste.txt') Out: {'t': 5, 'e': 4, 'x': 1, 'o': 3, 'd': 2, 's': 3, 'c': 1, 'm': 1, 'a': 1, 'l': 1, 'g': 2, 'u': 1, 'n': 1, 'í': 1, 'i': 1} In : hist[‘t’] Out: 5Texto de teste com alguns dígitos. 123
Sumário
• Dados estruturados. Dicionários. • Vetores e dicionários de dicionários.
• Resolução de problemas
§ Frequências / Histogramas
Massa Molecular de um Composto [1]
• Faça um programa que determina a massa molecular de uma molécula,
dada a sua fórmula química.
• Os dados do composto estão num dicionário, que implementa a tabela
periódica, em que a chave é o símbolo químico do elemento, e inclui outra informação (número atómico, nome e massa atómica).
• Exemplo: água = ‘H2O’ -> 18.0152
§ o elemento ‘H’, hidrogénio, está (H) presente com 2 átomos na molécula
de água
§ o elemento ‘O’, oxigénio, está presente com 1 átomo na molécula de água.
§ A massa molecular é calculada a parPr das massas atómicas do hidrogénio
(1.00794) e do oxigénio (15.9994), i.e.
Massa Molecular de um Composto [2]
• Para resolver este problema é necessário saber informações sobre o
elemento com determinado símbolo químico e, em parPcular, a sua massa atómica, i.e. implementar (parcialmente) a tabela periódica.
• A informação relevante da tabela periódica está presente num ficheiro
elementos.txt (na figura) que, após a primeira linha, tem uma linha por cada elemento, contendo o número atómico, símbolo químico, nome, e
massa atómica. number symbol name mass
1 H Hydrogen 1.00794 2 He Helium 4.002602 3 Li Lithium 6.941 4 Be Beryllium 9.012182 5 B Boron 10.811 6 C Carbon 12.0107 7 N Nitrogen 14.0067 8 O Oxygen 15.9994 9 F Fluorine 18.9984032 10 Ne Neon 20.1797 ……..
Resolução – Problema [1]
1. Compreender totalmente o problema.
§ O problema é claro.
2. Caracterizar o problema.
• Problema: Obter a fórmula química e massa de um composto.
• Entrada: (string) nomeFich. (Dict) composto
• Saída: (string) a fórmula química do composto, (float) massa do composto
3. Generalizar o problema (sempre que for possível).
Resolução – Algoritmo [1]
4. Desenhar o algoritmo para resolver o problema.
a) Conceber o algoritmo, decompondo o problema em sub-problemas. Podemos decompor este problema em 4 sub-problemas
1. Ler o ficheiro com a informação química
• Obter um dicionário com símbolos e massa atómicas dos
elementos do composto
2. A par9r da fórmula química do composto, obter as suas
componentes (e.g., separar H2O em [(’H’,2), (‘O’,1)]
• Processar strings
3. Para cada componente obter a respe9va massa
Resolução – Algoritmo [2]
b) Iden9ficar, caracterizar e generalizar cada sub-problema. [1]
• Problema: Criar a tabela periódica.
• Entrada: Nada (assume-se o nome do ficheiro). • Saída: (dict) tabela periódica
5. Para cada sub-problema, desenhar o algoritmo para o resolver.
Sub-problema: Criar a tabela periódica
1. Inicializar a tabela a vazio
2. Abrir o ficheiro para leitura.
3. Desprezar a primeira linha.
4. Para cada linha do ficheiro
§ Criar um dicionário com informação de cada elemento
§ Acrescentá-lo à tabela
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Sub-problema: Leitura da tabela periódica
def lerTabelaPeriodica():
""" ... """
tabela = {}
fich = open(‘tabela_periodica.txt’, 'r’) fich.readline() # despreza a primeira linha
for line in fich.readlines(): linha = line.split('\t’) chave = linha[1]
info = {'nAtom’: int(linha[0]),\
'nome' : linha[2], 'mAtom': float(linha[3])} elem = {chave : info}
tabela.update(elem) fich.close()
return tabela
number symbol name mass 1 H Hydrogen 1.00794 1\tH\tHydrogen\t1.00794\n
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respetivo algoritmo e testar o “sub-programa”.
• Sub-problema: Leitura da tabela periódica
In : tabela = lerTabelaPeriodica() In : tabela
Out: {'H': {'nAtom’: 1, 'nome': 'Hydrogen', 'mAtom': 1.00794}, 'He': {'nAtom’: 2, 'nome': 'Helium', 'mAtom': 4.002602},
'Li': {'nAtom': 3, 'nome': 'Lithium', 'mAtom': 6.941},
'Be': {'nAtom': 4, 'nome': 'Beryllium', 'mAtom': 9.012182}, 'B': {'nAtom': 5, 'nome': 'Boron', 'mAtom': 10.811},
'C': {'nAtom': 6, 'nome': 'Carbon', 'mAtom': 12.0107}, 'N': {'nAtom': 7, 'nome': 'Nitrogen', 'mAtom': 14.0067}, 'O': {'nAtom': 8, 'nome': 'Oxygen', 'mAtom': 15.9994},
'F': {'nAtom': 9, 'nome': 'Fluorine', 'mAtom': 18.9984032}, ...
In : tabela['N'].nAtom Out: 7
In : tabela['O'].mAtom Out: 15.9994
number symbol name mass
1 H Hydrogen 1.00794 2 He Helium 4.002602 3 Li Lithium 6.941 4 Be Beryllium 9.012182 5 B Boron 10.811 6 C Carbon 12.0107 7 N Nitrogen 14.0067 8 O Oxygen 15.9994 9 F Fluorine 18.9984032 10 Ne Neon 20.1797 …….. tabela_periodica.txt
Resolução – Algoritmo [2]
b) Identificar, caracterizar e generalizar cada sub-problema. [1]
• Problema: Obter Componentes do composto. • Entrada: (string) fórmula química do composto
• Saída: (lista) lista de componentes, em que cada um é um tuplo (Símbolo Químico, Número)
Por exemplo de ‘H20’ obter [(’H’,2), (‘O’,1)]
Algoritmo:
Início = 0 Partes = []
Enquanto não se chegar ao fim da fórmula,
Ler o componente que começa na posição Início atualizando esse Início Desdobrar o componente em símbolo químico e número de átomos Acrescentar o componente à lista das partes
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Sub-problema: Obter as componentes do composto
• Antes de testar esta função tem de se definir as sub-funções
obterParteDesde e desdobrar.
def decomporFormula(composto): """ ... """
partes = [] inicio = 0
while inicio < len(composto):
(parte,inicio) = obterParteDesde(composto,inicio) atom_numb = desdobrar(parte)
partes.append(atom_numb)
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter uma parte do composto a par9r da posição i. • Entrada: (string) fórmula do composto e (int) posição inicial
• Saída: (string) formula química da componente e (int) posição inicial da próxima parte
Algoritmo:
Começar a parte com o caracter (maiúsculo) na posição inicial Avançar a posição
Enquanto não se chegar ao fim da fórmula e não se encontrar uma letra maiúscula,
Avançar a posição
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respetivo algoritmo e testar o “sub-programa”.
• Sub-problema: Obter uma componentes do composto a partir de
uma dada posição
• Testar:
def obterParteDesde(composto, i): """ ... """
parte = composto[i] i = i + 1
while i < len(composto) and not composto[i].isupper():
part = part + composto[i] i = i + 1 return (part, i) In : obterParteDesde('H2O',0) Out: ('H2', 2) In : obterParteDesde('H2O',2) Out: ('O', 3)
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Problema: Desdobrar uma componente do composto. • Entrada: (string) fórmula da componente
• Saída: tuplo (simbolo, número) ;
e.g. de ’H2’ obter (‘H’,2) e de ‘O’, obter (‘O’,1) .
def desdobrar(parte): """ ... """
atom = parte[0] i = 1
n = len(parte)
while i < n and not parte[i].isdigit():
atom = atom + parte[i] i = i + 1
if i == n: num = 1 else:
num = int(parte[i:n])
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Podemos agora testar as várias funções que implementamos para
obter as partes de uma fórmula.
In : desdobrar('H2') Out: ('H', 2) In : desdobrar('O') Out: ('O', 1) In : decomporFormula('H2O') Out: [('H', 2), ('O', 1)] In : decomporFormula('H2SO4') Out: [('H', 2), ('S', 1), ('O', 4)] In : decomporFormula('C2H5OH') Out: [('C', 2), ('H', 5), ('O', 1), ('H', 1)]
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar o
respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter a massa de um componente • Entrada: (tuplo) componente e (dict) tabela • Saída: (float) massa do componente
Algoritmo:
Consultar a tabela e obter a massa atómica do elemento do componente Obter o número de átomos do elemento no componente
Mul9plicar os valores para obter a massa
{'H’ : {'nAtom': '1', 'nome': 'Hydrogen’, 'mAtom': 1.00794}, 'He': {'nAtom': '2', 'nome': 'Helium’, 'mAtom': 4.002602}, 'Li': {'nAtom': '3', 'nome': 'Lithium’, 'mAtom': 6.941},
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter a massa de um componente • Entrada: (tuplo) componente e (list) tabela • Saída: (float) massa do componente
def obterMassaComponente(componente, tabela): """ ... """
mAtomic = tabela[componente[0]]['mAtom'] nAtoms = componente[1]
massa = nAtoms * mAtomic
return massa
{'H’ : {'nAtom': '1', 'nome': 'Hydrogen’, 'mAtom': 1.00794}, 'He': {'nAtom': '2', 'nome': 'Helium’, 'mAtom': 4.002602}, 'Li': {'nAtom': '3', 'nome': 'Lithium’, 'mAtom': 6.941},
Resolução – Implementação [3]
6. Para cada sub-problema (começando pelos mais simples), implementar
o respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter a massa de um componente • Entrada: (tuplo) componente e (list) tabela • Saída: (float) massa do componente
In : tabela = lerTabelaPeriodica() In : obterMassaComponente(('H',2), tabela) Out: 2.01588 In : obterMassaComponente(('Li',3), tabela) Out: 20.823 In : obterMassaComponente(('S',1), tabela) Out: 32.065
{'H’ : {'nAtom': '1', 'nome': 'Hydrogen’, 'mAtom': 1.00794}, 'He': {'nAtom': '2', 'nome': 'Helium’, 'mAtom': 4.002602}, 'Li': {'nAtom': '3', 'nome': 'Lithium’, 'mAtom': 6.941},
Resolução – Implementação [3]
Finalmente podemos integrar os vários componentes na função principal
6. Para cada sub-problema (começando pelos mais simples), implementar o
respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter a massa do composto
• Entrada: (str) fórmula química do composto • Saída: (float) massa do composto
Algoritmo:
Ler a tabela periódica
Desdobrar a fórmula em componentes Inicializar a massa do composto a 0 Para cada componente da fórmula
Obter a massa do componente
Resolução – Implementação [3]
Finalmente podemos integrar os vários componentes na função principal
6. Para cada sub-problema (começando pelos mais simples), implementar o
respe9vo algoritmo e testar o “sub-programa”.
• Problema: Obter a massa de o composto
• Entrada: (str) fórmula química do composto • Saída: (float) massa do composto
def calcularMassa(composto): """ ... """
tabela = lerTabelaPeriodica()
partes = decomporFormula(composto) massa = 0
for parte in partes:
massa = massa + calcularMassa(parte, tabela)
Resolução – Implementação [3]
Podemos agora testar o pograma implementado, com vários compostos
In : água = 'H2O' In : calcularMassa(agua) Out: 18.01528 In : ácidoSulfúrico = 'H2SO4' In : calcularMassa(ácidoSulfúrico) Out: 98.07848 In : etanol = 'C2H5OH' In : calcularMassa(etanol) Out: 46.068439999999995 In : glicose = 'C6H12O6' In : calcularMassa(glicose) Out: 180.15588
Para saber Mais
• Consultar um dos livros de texto aconselhados.
• Por exemplo:
§ “Think Python: How to Think Like a Computer Scien9st ”:
cap. 11.
§ “Introduc9on to Computa9on and Programming Using Python”,