3
\$\begingroup\$

This reads a list of points from a file with a certain format:

<number of points>
x1 y1
x2 y2

How I can make it better?

from collections import namedtuple
Point = namedtuple('Point ', ['x', 'y'])
def read():
 ins = open("PATH_TO_FILE", "r")
 array = []
 first = True
 expected_length = 0
 for line in ins:
 if first:
 expected_length = int(line.rstrip('\n'))
 first = False
 else:
 parsed = line.rstrip('\n').split ()
 array.append(Point(int(parsed[0]), int(parsed[1])))
 if expected_length != len(array):
 raise NameError("error on read")
 return array
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 13, 2012 at 19:52
\$\endgroup\$
2
  • \$\begingroup\$ If you're dealing with points you might want to use a library like Shapely, which will give you a nice Point object. \$\endgroup\$ Commented Dec 14, 2012 at 3:25
  • \$\begingroup\$ @monkut, thx I'll see. \$\endgroup\$ Commented Dec 14, 2012 at 9:46

3 Answers 3

4
\$\begingroup\$

Another improvement is to use open as a context manager so that you don't have to remember to .close() the file object even if there are errors while reading.

def read():
 with open("FILE", "r") as f:
 array = []
 expected_length = int(f.next())
 for line in f:
 parsed = map(int, line.split())
 array.append(Point(*parsed))
 if expected_length != len(array):
 raise NameError('error on read')
 return array

See http://docs.python.org/2/library/stdtypes.html#file.close for more details.

answered Dec 14, 2012 at 4:28
\$\endgroup\$
0
3
\$\begingroup\$

You don't need all that expected_length and first=True stuff. You can treat a file as an iterator, and it will return objects until it quits, so you can just use the .next() method and throw item away, or save it to a variable if you wish. In that sense, it's best to write two functions-- one to deal with the file, and another to deal with a single line as provided by the file object.

def lineparse(line):
 ''' Parses a single line. '''
 # your code goes here
def fileparse(filepath):
 f = open(filepath, "r")
 n = int(f.next()) # this also advances your iterator by one line
 while True: 
 yield lineparse(f.next())
 f.close()
data = list(fileparse(filepath))
answered Dec 13, 2012 at 23:26
\$\endgroup\$
2
  • \$\begingroup\$ expected_length is a check that the supposed length of the array equals the amount of data, you can't just ignore it. \$\endgroup\$ Commented Dec 14, 2012 at 3:54
  • \$\begingroup\$ Ah ignore me, I've just noticed you use n = to get the expected length. Still a bit confusing that you say you don't need expected_length though. \$\endgroup\$ Commented Dec 14, 2012 at 4:08
3
\$\begingroup\$

Not that big a change but you don't need to worry about stripping out \ns as the split and int functions will take care of that. Secondly, as already pointed out, you can grab the first line by just calling .next() then use a loop for the remaining lines.

def read():
 ins = open("FILE", "r")
 array = []
 expected_length = int(ins.next())
 for line in ins:
 parsed = line.split()
 array.append(Point(int(parsed[0]), int(parsed[1])))
 if expected_length != len(array):
 raise NameError('error on read')
 ins.close()
 return array
answered Dec 14, 2012 at 4:10
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.