Manolo Dominguez Becerra
Manolo Dominguez Becerra

Reputation: 1373

Calculating atomic mass

Being new in Python... I want to design a program to calculate the atomic mass, given a molecule like this 'C14-H10-O'.

(I know, there are very beautiful programs created already but I want to create my own program and feel proud of my self.)

My code is almost finished BUT I have found a problem I cant solve.

Here is my code:

masas = {'H': 1.007825, 'C': 12.01, 'O': 15.9994, 
         'N': 14.0067, 'S': 31.972071, 'P': 30.973762}
elements_list = ['H','C','O', 'N', 'S','P']

def calcula_masa_atomica(molecula):
    """
    Calcula la masa atomica de una molecula
    """
    import re
    masa = 0.0
    #Primero creamos los
    molecula = re.sub('[-]', '', molecula) #Remove "-"
    molecula = (re.split('(\d+)',molecula))#split numbers and elements
    for i, ch in enumerate(molecula):
        if ch in elements_list: #If the element is in the elements_list,
            element_mass = masas.get(ch)# Get the mass of this element
            if molecula[i + 1].isdecimal(): #If the inmediately item is decimal
                masa += element_mass * int(molecula[i + 1])# Add the mass of this element by the number of times that element is present. In each iteration, the masses of each element will be added and stored in the mass object
            # If not, just add that element's mass to the sum.
            else:
                masa += element_mass

    return masa    

No problem is the molecule looks like 'C14-H10-O2' BUT if some of the elements have not one digit after the element, Python reply with this error.

IndexError: list index out of range

I know what problem I have is but I do not how I can solve it.

Upvotes: 0

Views: 1715

Answers (1)

azro
azro

Reputation: 54168

Using the regex '(([A-Z])([0-9]*))' you'll find all group in the molecule, like this

'C14-H10-O2' > [('C14', 'C', '14'), ('H10', 'H', '10'), ('O2', 'O', '2')]
'H2O' > [('H2', 'H', '2'), ('O', 'O', '')]

Then iterate over each group, and from atom find the mass, then multiply by the number (or 1 if there wasn't)

def calcula_masa_atomica(molecula):
    masa = 0.0
    for group, atom, nb in re.findall(r'(([A-Z])([0-9]*))', molecula):
        element_mass = masas.get(atom, 0)
        masa += element_mass * int(nb or 1)
    return masa

Using list comprehension grammar, it's just :

def calcula_masa_atomica(molecula):
    return sum(masas.get(atom, 0) * int(nb or 1) for _, atom, nb in re.findall(r'(([A-Z])([0-9]*))', molecula))

Upvotes: 1

Related Questions