0% found this document useful (0 votes)
10 views

13 Object Oriented Programming - Python Solutions 1.5 Documentation

Uploaded by

Sammy Ay-man
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

13 Object Oriented Programming - Python Solutions 1.5 Documentation

Uploaded by

Sammy Ay-man
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

13 Object Oriented Programming

13.1 Exercises

13.1.1 Exercise
Modelize a sequence with few attributes and methods

1 class Sequence(object):
2
3 def __init__(self, identifier, comment, seq):
4 self.id = identifier
5 self.comment = comment
6 self.seq = self._clean(seq)
7
8
9 def _clean(self, seq):
10 """
11 remove newline from the string representing the sequence
12 :param seq: the string to clean
13 :return: the string without '\n'
14 :rtype: string
15 """
16 return seq.replace('\n')
17
18
19 def gc_percent(self):
20 """
21 :return: the gc ratio
22 :rtype: float
23 """
24 seq = self.seq.upper()
25 return float(seq.count('G') + seq.count('C')) / len(seq)
26
27
28
29
30 dna1 = Sequence('gi214', 'the first sequence', 'tcgcgcaacgtcgcctacatctcaagattca')
31 dna2 = Sequence('gi3421', 'the second sequence', 'gagcatgagcggaattctgcatagcgcaagaatgcggc')

sequence.py .

13.1.2 Exercise
Instanciate 2 sequences using your Sequence class, and draw schema representing the namespaces

13.1.3 Exercise
Can you explain this result (draw namespaces to explain) ? how to modify the class variable class_attr

1 class MyClass(object):
2
3 class_attr = 'foo'
4
5 def __init__(self, val):
6 self.inst_attr = val
7
8
9 a = MyClass(1)
10 b = MyClass(2)
11
12 print(a.inst_attr)
13 1
14 print(b.inst_attr)
15 2
16
17 print(a.class_attr == b.class_attr)
18 True
19 print(a.class_attr is b.class_attr)
20 True
21
22 b.class_attr = 4
23
24 print(a.class_attr)
25 4
26 del a.class_attr
27
28 MyClass.class_attr = 4

class_attribute.py .

13.1.4 Exercise
Write the definition of a Point class. Objects from this class should have a

a method show to display the coordinates of the point


a method move to change these coordinates.
a method dist that computes the distance between 2 points.

Note: the distance between 2 points A(x0, y0) and B(x1, y1) can be compute
−−−−−−−−−−−−−−−−−−−
d(AB) = √(x1 − x0))2 + (y1 − y0)2

(http://www.mathwarehouse.com/algebra/distance_formula/index.php)

The following python code provides an example of the expected behaviour of objects belonging to this class:

>>> p1 = Point(2, 3)
>>> p2 = Point(3, 3)
>>> p1.show()
(2, 3)
>>> p2.show()
(3, 3)
>>> p1.move(10, -10)
>>> p1.show()
(12, -7)
>>> p2.show()
(3, 3)
>>> p1.dist(p2)
1.0

1 import math
2
3
4 class Point(object):
5 """Class to handle point in a 2 dimensions space"""
6
7 def __init__(self, x, y):
8 """
9 :param x: the value on the X-axis
10 :type x: float
11 :param y: the value on the Y-axis
12 :type y: float
13 """
14 self.x = x
15 self.y = y
16
17
18 def show(self):
19 """
20 :return: the coordinate of this point
21 :rtype: a tuple of 2 elements (float, float)
22 """
23 return self.x, self.y
24
25
26 def move(self, x, y):
27 """
28 :param x: the value to move on the X-axis
29 :type x: float
30 :param y: the value to move on the Y-axis
31 :type y: float
32 """
33 self.x += x
34 self.y += y
35
36
37 def dist(self, pt):
38 """
39 :param pt: the point to compute the distance with
40 :type pt: :class:`Point` object
41 :return: the distance between this point ant pt
42 :rtype: int
43 """
44 dx = pt.x - self.x
45 dy = pt.y - self.y
46 return math.sqrt(dx ** 2 + dy ** 2)

point.py .

13.1.5 Exercise
Use OOP to modelize restriction enzyme, and sequences.

the sequence must implement the following methods

enzyme_filter which take as a list of enzymes as argument and return a new list containing the
enzymes which have binding site in sequence

the restriction enzyme must implements the following methods

binds which take a sequence as argument and return True if the sequence contains a binding
site, False otherwise.

solve the exercise 7.1.3 Exercise using this new implementation.

1
2 class Sequence(object):
3
4 def __init__(self, identifier, comment, seq):
5 self.id = identifier
6 self.comment = comment
7 self.seq = self._clean()
8
9 def _clean(self):
10 """
11
12 :param seq:
13 :return:
14 """
15 return self.seq.replace('\n')
16
17 def enzyme_filter(self, enzymes):
18 """
19
20 :param enzymes:
21 :return:
22 """
23 enzymes_which_binds = []
24 for enz in enzymes:
25 if enz.binds(self.seq):
26 enzymes_which_binds.append(enz)
27 return
28
29
30 class RestrictionEnzyme(object):
31
32 def __init__(self, name, binding, cut, end, comment=''):
33 self._name = name
34 self._binding = binding
35 self._cut = cut
36 self._end = end
37 self._comment = comment
38
39 @property
40 def name(self):
41 return self._name
42
43 def binds(self, seq):
44 """
45
46 :param seq:
47 :return:
48 """
49 return self.binding in seq.seq

enzyme.py .

13.1.6 Exercise
refactor your code of 8.1.16 Exercise in OOP style programming. implements only

size: return the number of rows, and number of columns


get_cell: that take the number of rows, the number of columns as parameters, and returns the
content of cell corresponding to row number col number
set_cell: that take the number of rows, the number of columns as parameters, and a value and
set the value val in cell specified by row number x column number
to_str: return a string representation of the matrix
mult: that take a scalar and return a new matrix which is the scalar product of matrix x val

you can change the name of the methods to be more pythonic

1
2
3
4
5 class Matrix(object):
6
7 def __init__(self, row, col, val=None):
8 self._row = row
9 self._col = col
10 self._matrix = []
11 for i in range(row):
12 c = [val] * col
13 self._matrix.append(c)
14
15 def size(self):
16 return self._row, self._col
17
18 def get_cell(self, row, col):
19 self._check_index(row, col)
20 return self._matrix[i][j]
21
22 def matrix_set(self, row, col, val):
23 self._check_index(row, col)
24 self._matrix[row][col] = val
25
26 def __str__(self):
27 s = ''
28 for i in range(self._row):
29 s += self._matrix[i]
30 s += '\n'
31 return s
32
33 def _check_index(self, row, col):
34 if not (0 < row <= self._row) or not (0 < col <= self._col):
35 raise IndexError("matrix index out of range")

matrix_obj.py .

13.1.7 Exercise
Use the code to read multiple sequences fasta file in procedural style and refactor it in OOP style. use the file
abcd.fasta to test your code.

What is the benefit to use oop style instead of procedural style?

1 class Sequence(object):
2
3 def __init__(self, id_, sequence, comment=''):
4 self.id = id_
5 self.comment = comment
6 self.sequence = sequence
7
8 def gc_percent(self):
9 seq = self.sequence.upper()
10 return float(seq.count('G') + seq.count('C')) / float(len(seq))
11
12 class FastaParser(object):
13
14
15 def __init__(self, fasta_path):
16 self.path = fasta_path
17 self._file = open(fasta_path)
18 self._current_id = ''
19 self._current_comment = ''
20 self._current_sequence = ''
21
22 def _parse_header(self, line):
23 """
24 parse the header line and _current_id|comment|sequence attributes
25 :param line: the line of header in fasta format
26 :type line: string
27 """
28 header = line.split()
29 self._current_id = header[0][1:]
30 self._current_comment = ' '.join(header[1:])
31 self._current_sequence = ''
32
33 def __iter__(self):
34 return self
35
36 def next(self):
37 """
38 :return: at each call return a new :class:`Sequence` object
39 :raise: StopIteration
40 """
41 for line in self._file:
42 if line.startswith('>'):
43 # a new sequence begin
44 if self._current_id != '':
45 new_seq = Sequence(self._current_id,
46 self._current_sequence,
47 comment=self._current_comment)
48 self._parse_header(line)
49 return new_seq
50 else:
51 self._parse_header(line)
52 else:
53 self._current_sequence += line.strip()
54 if not self._current_id and not self._current_sequence:
55 self._file.close()
56 raise StopIteration()
57 else:
58 new_seq = Sequence(self._current_id,
59 self._current_sequence,
60 comment=self._current_comment)
61 self._current_id = ''
62 self._current_sequence = ''
63 return new_seq
64
65
66 if __name__ == '__main__':
67 import sys
68 import os.path
69
70 if len(sys.argv) != 2:
71 sys.exit("usage fasta_object fasta_path")
72 fasta_path = sys.argv[1]
73 if not os.path.exists(fasta_path):
74 sys.exit("No such file: {}".format(fasta_path))
75
76 fasta_parser = FastaParser(fasta_path)
77 for sequence in fasta_parser:
78 print("----------------")
79 print("{seqid} = {gc:.3%}".format(gc=sequence.gc_percent(),)
80 seqid = sequence.id)

fasta_object.py .

You might also like