I'd say that shorter shouldn't be the goal in itself, unless you're golfing (in which case, you want to be on Code Golf and Coding Challenges). A better criterion is to have the simplest code that achieves the desired aim.
A major contribution to simplicity is to replace the explicit close of f
with a with
block:
with open('text.txt', 'r') as f:
# do the addition
# f is closed before we get here
Another simplification is to use sum
/map
as suggested in styvane's answer; however, it may be more efficient to read the file a line at a time rather than slurping the entire contents into memory if it's very long.
We could also make the code more efficient by compiling the regular expression just once.
Following that, we might want to make the code more reusable and testable. I would separate into a function that does the summing but doesn't care where the stream comes from (file, pipe, socket, string), and have tests for that. Then simply call it with the input file stream.
That reusable function including unit-tests looks like this:
import re
def sum_integers(stream):
"""Return the total of all the digit strings found in the input stream
>>> from io import StringIO
>>> sum_integers(StringIO(''))
0
>>> sum_integers(StringIO('1'))
1
>>> sum_integers(StringIO('-1'))
1
>>> sum_integers(StringIO('a1z'))
1
>>> sum_integers(StringIO('1-2'))
3
>>> sum_integers(StringIO('1-2\\n3.4'))
10
"""
digit_pattern = re.compile(r'\d+')
return sum(sum(map(int, digit_pattern.findall(line))) for line in stream)
if __name__ == "__main__":
import doctest
doctest.testmod()
And we can use it very simply:
def print_sum_of_integers_from_file(filename):
print(sum_integers(open(filename, 'r')))
That's not shorter, but it is better in the ways I've described (more efficient, flexible and maintainable).