The answer
s, g1, g2, g3, g4 = [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]
How I derived the answer
From the prompt of the ipython shell:
In [38]: cat marks.txt
s1
g11
g12
g13
g14
s2
g21
g22
g23
g24
s3
g31
g32
g33
g34
In [39]: zip(*[open('marks.txt')]*5)
Out[39]: 
[('s1\n', 'g11\n', 'g12\n', 'g13\n', 'g14\n'),
 ('s2\n', 'g21\n', 'g22\n', 'g23\n', 'g24\n'),
 ('s3\n', 'g31\n', 'g32\n', 'g33\n', 'g34\n')]
In [40]: zip(*zip(*[open('marks.txt')]*5))
Out[40]: 
[('s1\n', 's2\n', 's3\n'),
 ('g11\n', 'g21\n', 'g31\n'),
 ('g12\n', 'g22\n', 'g32\n'),
 ('g13\n', 'g23\n', 'g33\n'),
 ('g14\n', 'g24\n', 'g34\n')]
In [41]: [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]
Out[41]: 
[['s1', 's2', 's3'],
 ['g11', 'g21', 'g31'],
 ['g12', 'g22', 'g32'],
 ['g13', 'g23', 'g33'],
 ['g14', 'g24', 'g34']]
In [42]: s, g1, g2, g3, g4 = [[line.strip() for line in group_of_lines] for group_of_lines in zip(*zip(*[open('marks.txt')]*5))]
In [43]: print '\n'.join(map(str,(s,g1,g2,g3,g4)))
['s1', 's2', 's3']
['g11', 'g21', 'g31']
['g12', 'g22', 'g32']
['g13', 'g23', 'g33']
['g14', 'g24', 'g34']
In [44]:
A line by line commentary on "How I derived the answer"
[38]
My personal version of the marks.txt data file
[39]
The crux of the procedure, the
grouper
procedure shamelessly adapted from the itertools module fine
docs.
A file object can be simply understood as an iterator that returns the
file content line by line, so we start with a list containing 5
(identical) copies of a file iterator that returns the content of our
data file, and pass the elements of this list (by using the * star
operator) to the zip builtin function, that returns a list of tuples
with an element from each one of its arguments, e.g.:
In [44]: zip(*[[1,2,3],[10,20,30]])
Out[44]: [(1, 10), (2, 20), (3, 30)]
Because zip is passsed five identical copies of the same file
iterator, it builds a list of tuples containing the first five lines,
the second five lines, ..., of our file.
[40]
But we want it the other way around! Or, in other words, we want to
transpose our list of tuples.
Transposition of a sequence of sequences is usually obtained with an
idiom that's very similar to what we've just seen...
In [45]: zip(*[(1, 10), (2, 20), (3, 30)])
Out[45]: [(1, 2, 3), (10, 20, 30)]
[41]
What's the matter with all these '\n' newline charaters? Let's strip
them away...
Our problem is that we have a double nesting, say a list of lists
containing the elements that we want to correct...
We have no choice but to unpack the elements with a double loop and
then pack twice our corrected, stripped items again in a list of
lists...
[42]
We have a list of lists, whose elements are exactly what we want to
associate to our variable names, this can be done in one sweep using
what is called _sequence unpacking...
The statement 42 represents the compact solution to our problem. By a long time we all knew that 42 is the answer, now eventually we know the question too...
[43]
Just to verify that what we have in our variables is the result we are
looking for.