1

I am using regex to calculate the value of a string that contains real numbers and addition, such as '3.4+5.2'. This is the code:

import re

a = str(raw_input())

counter = a.count('+')
for i in range(counter):
    add = re.match('([\+\-]?\d+(?:\.\d+)?)\+([\+\-]?\d+(?:\.\d+)?)', a)
    temp = float(add.groups()[0]) + float(add.groups()[1])
    a = re.sub('([\+\-]?\d+(?:\.\d+)?)\+([\+\-]?\d+(?:\.\d+)?)', str(temp), a)
print a

It works fine for:

>>> a = '3+4'
'7.0'
>>> a = '3+4+5'
'12.0'

But, when I try to add more than twice:

>>> a = '3+4+5+6'
7.07.0
    temp = float(add.groups()[0]) + float(add.groups()[1])
AttributeError: 'NoneType' object has no attribute 'groups'

Why does this error appear, how can it be fixed?

8
  • re.match finds nothing, so there's no group. Commented Dec 13, 2015 at 1:42
  • re.match returns None if there's no match. Trying to access groups raises AttributeError. (None.groups(...)) Commented Dec 13, 2015 at 1:42
  • @timgeb I understand what the error means, but there is something to be found.. and it works in the first two examples. Commented Dec 13, 2015 at 1:43
  • Ah...why don't just a.split('+'), without regex? Commented Dec 13, 2015 at 1:44
  • @janedoe, After the first iteration, a become 7.07.0 which does not have + -> no match. Commented Dec 13, 2015 at 1:45

1 Answer 1

1

re.match() returns None if there's no match. Trying to access groups raises AttributeError. (None.groups(...))

After the first iteration, a become 7.07.0 which does not have +. The reason is re.sub replace all matches, not only the first match.

To make it replace only the first occurence, you need to specify count:

a = re.sub('([\+\-]?\d+(?:\.\d+)?)\+([\+\-]?\d+(?:\.\d+)?)', str(temp), a, count=1)

As Kevin Guan commented, using str.split() will be better; easy to read, simple:

>>> '3+4+5+6'.split('+')
['3', '4', '5', '6']
>>> map(float, '3+4+5+6'.split('+'))
[3.0, 4.0, 5.0, 6.0]
>>> sum(map(float, '3+4+5+6'.split('+')))
18.0
Sign up to request clarification or add additional context in comments.

10 Comments

This wouldn't work for me, because I will add other operators later. I still don't understand how my code works for '3+4+5' and not for '3+4+5+6'. The second one should be transformed into '7.0+5+6', then to '12.0+6' and then to '18.0'. Why is that not happening?
@janedoe, Because there are two matches in 3+4+5+6. re.sub without count argument, replaces them all. I updated the answer to mention it.
Could you show me how to do this using regex, as I tried?
@janedoe, I updated the answer to include it. Please reload this page if you see old answer.
@falsetru: No problem :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.