8 Dive into Functions

8.1 Exercises

8.1.1 Exercise

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

Hint locals print a dictionary with local variable as keys and their respective values.

_images/cf_exo_1.png
x = 4

def func():
   y  = 5
   print(locals())

>>> func()
{'y': 5}
>>> print(x)
4
_images/spacer.png

8.1.2 Exercise

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

Hint locals print a dictionary with local variable as keys and their respective values.

_images/cf_exo_2.png
x = 4

def func():
   y = 5
   x = 8
   print(locals())
   x = x + 2

>>> y = func()
{'y': 5, 'x': 8}
>>>
>>> print(y)
None
>>> print(x)
4
_images/spacer.png

8.1.3 Exercise

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

Hint locals print a dictionary with local variable as keys and their respective values.

_images/cf_exo_3.png
x = 4

def func(a):
   y = x + 2
   print(locals())
   x = y
   return y

>>> y = func(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in func
UnboundLocalError: local variable 'x' referenced before assignment

Unlike what we might think in y = x + 2 x is not get from the global scope. As soon as you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable in the outer scope. even if the assignment appear later in code. Here x = y make x as local variable whatever you are in func. so at line y = x + 2 we try to use the local variable x but we have to asign it a value (it is done later) so Python raise an UnboundLocalError (see python faq for details)

_images/spacer.png

8.1.4 Exercise

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

Hint locals print a dictionary with local variable as keys and their respective values.

_images/cf_exo_4.png
x = 4

def func(a):
   x = x + 2
   print(locals())
   return x

y = func(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in func
UnboundLocalError: local variable 'x' referenced before assignment

print y
print y == x
_images/spacer.png

8.1.5 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_5.png
x = 4

def func(x):
   x = x + 2
   return x

y = func(x)

>>> print(x)
4
>>> print(y == x)
False
_images/spacer.png

8.1.6 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_6.png
def func():
   y = x
   return y

>>> x = 4
>>> z = func()
>>>
>>> print(x)
4
>>> print(z)
4
>>> print(id(z) == id(x))
True
_images/spacer.png

8.1.7 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_7.png
x = 4

def func(x=5):
   x = x + 2
   return x

>>> y = func(x)
>>>
>>> print(x)
4
>>> print(y)
6
_images/spacer.png

8.1.8 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

Hint locals print a dictionary with local variable as keys and their respective values.

_images/cf_exo_8.png
x = 4

def func(a):
   global x
   def func2():
      print(locals())
      y = x + 4
      return y
   z = func2()
   return z

y = func(x)
{}
>>> print(x)
4
>>> print(y)
8
_images/spacer.png

8.1.9 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_9.png
x = {'a' : 4}

def func(a):
   a['b'] = 5
   return a

y = func(x)

>>> print(x)
{'a': 4, 'b': 5}
>>> print y
{'a': 4, 'b': 5}
>>> print(x is y)
True
_images/spacer.png

8.1.10 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_10.png
x = {'a' : 4}

def func(a):
   a['b'] = 5

y = func(x)

>>> print(x)
{'a': 4, 'b': 5}
>>> print(y)
None
_images/spacer.png

8.1.11 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_11.png
x = {'a' : 4}

def func(a):
   x['b'] = 5
   def func2():
      a['b'] = 6
   return a

y = func(x)

print x
{'a': 4, 'b': 5}
print y
{'a': 4, 'b': 5}
a refer to same object as x
in func x does not exist, so x refer to global variable x
we mutate x
func2 is never executed
we return a so the same object referred by x
so y refer also the same object as x
_images/spacer.png

8.1.12 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_12.png
x = {'a' : 4}

def func(a):
   x['b'] = 5
   def func2():
      a['b'] = 6
   func2()
   return a

y = func(x)

print(x)
{'a': 4, 'b': 6}
in this code func2 is executed
a is not in func2 namespace so python find it in enclosing namespace func
a refer the same object as x
_images/spacer.png

8.1.13 Exercice

Without executing the code in Python interpreter, can you determine what the code below print out. help you by drawing diagram.

_images/cf_exo_13.png
x = {'a' : 4}

def func(a):
   x['b'] = 5
   def func2(x):
      x['b'] = 6
   func2(a.copy())
   return a

y = func(x)

print(x)
{'a': 4, 'b': 5}
in this code x a variable x is defined locally in func2 and hide the global variable x
this local x refer to a shallow copy of the func local variable a which refer to the same object as global variable x
so func2 does not do a side effect on dictionary referred by x as in previous example.
_images/spacer.png

8.1.14 Exercise

Write a function translate that have a nucleic sequence as parameter, and return the translate sequence. We give you a genetic code :

code = {  'ttt': 'F', 'tct': 'S', 'tat': 'Y', 'tgt': 'C',
           'ttc': 'F', 'tcc': 'S', 'tac': 'Y', 'tgc': 'C',
           'tta': 'L', 'tca': 'S', 'taa': '*', 'tga': '*',
           'ttg': 'L', 'tcg': 'S', 'tag': '*', 'tgg': 'W',
           'ctt': 'L', 'cct': 'P', 'cat': 'H', 'cgt': 'R',
           'ctc': 'L', 'ccc': 'P', 'cac': 'H', 'cgc': 'R',
           'cta': 'L', 'cca': 'P', 'caa': 'Q', 'cga': 'R',
           'ctg': 'L', 'ccg': 'P', 'cag': 'Q', 'cgg': 'R',
           'att': 'I', 'act': 'T', 'aat': 'N', 'agt': 'S',
           'atc': 'I', 'acc': 'T', 'aac': 'N', 'agc': 'S',
           'ata': 'I', 'aca': 'T', 'aaa': 'K', 'aga': 'R',
           'atg': 'M', 'acg': 'T', 'aag': 'K', 'agg': 'R',
           'gtt': 'V', 'gct': 'A', 'gat': 'D', 'ggt': 'G',
           'gtc': 'V', 'gcc': 'A', 'gac': 'D', 'ggc': 'G',
           'gta': 'V', 'gca': 'A', 'gaa': 'E', 'gga': 'G',
           'gtg': 'V', 'gcg': 'A', 'gag': 'E', 'ggg': 'G'
      }

8.1.14.1 bonus

This function have to take the phase as parameter

 1genetic_code = { 'ttt': 'F', 'tct': 'S', 'tat': 'Y', 'tgt': 'C',
 2           'ttc': 'F', 'tcc': 'S', 'tac': 'Y', 'tgc': 'C',
 3           'tta': 'L', 'tca': 'S', 'taa': '*', 'tga': '*',
 4           'ttg': 'L', 'tcg': 'S', 'tag': '*', 'tgg': 'W',
 5           'ctt': 'L', 'cct': 'P', 'cat': 'H', 'cgt': 'R',
 6           'ctc': 'L', 'ccc': 'P', 'cac': 'H', 'cgc': 'R',
 7           'cta': 'L', 'cca': 'P', 'caa': 'Q', 'cga': 'R',
 8           'ctg': 'L', 'ccg': 'P', 'cag': 'Q', 'cgg': 'R',
 9           'att': 'I', 'act': 'T', 'aat': 'N', 'agt': 'S',
10           'atc': 'I', 'acc': 'T', 'aac': 'N', 'agc': 'S',
11           'ata': 'I', 'aca': 'T', 'aaa': 'K', 'aga': 'R',
12           'atg': 'M', 'acg': 'T', 'aag': 'K', 'agg': 'R',
13           'gtt': 'V', 'gct': 'A', 'gat': 'D', 'ggt': 'G',
14           'gtc': 'V', 'gcc': 'A', 'gac': 'D', 'ggc': 'G',
15           'gta': 'V', 'gca': 'A', 'gaa': 'E', 'gga': 'G',
16           'gtg': 'V', 'gcg': 'A', 'gag': 'E', 'ggg': 'G'
17      }
18
19def translate(nuc_seq, code):
20    
21    prot_seq = ''
22    n = 0
23    # to avoid to compute len(seq)/3 at each loop
24    # I compute it once and use a reference
25    # it could be expensive if the sequence is very long.
26
27    # another way to determine the end of looping
28    # stop_iteration = len(nuc_seq)
29    # while (start + 2) < stop_iteration:
30    cycle = len(nuc_seq)//3
31    while n < cycle:
32        start = n * 3
33        end = start + 3
34        codon = nuc_seq[start:end]
35        codon = codon.lower()
36        if codon in code:
37            prot_seq += code[codon] 
38        else:
39            raise RuntimeError("unknow codon: " + codon)
40        n += 1
41        # if use the other looping solution
42        # n += 3
43    return prot_seq
44        
45def translate2(nuc_seq, code, phase = 1):
46    prot_seq = ''
47    if 0 < phase < 4 :
48        start = phase - 1
49        nuc_seq = nuc_seq[start:]
50    elif -4 < phase < 0:
51        start = -phase - 1
52        nuc_seq = nuc_seq[::-1]
53        nuc_seq = nuc_seq[start:]
54    prot_seq = translate(nuc_seq, code)
55    return prot_seq

translate.py .

8.1.15 Exercise

Write a program that calculates the similarity of 2 RNA sequences.

  • To compute the similarity you need to parse a file containing the similarity matrix.

    Hint: use the module containing the functions that handle a matrix from previous chapter. put this matrix.py file in a directory named “my_python_lib” in your home or Desktop and import it in your current program (the similarity script must be placed elsewhere).

  • The similarity of the 2 sequences is the sum of base similarities. so you have to compare the first base of two sequences and use the matrix to get the similarity from the similarity table, on so on for all bases then sum these similarities.

First implementation (list of columns)

  1"""
  2Implementation of simple matrix 
  3"""
  4
  5
  6def create(row_num, col_num, val=None):
  7	"""
  8	:param row_num: the number of rows
  9	:type row_num: int
 10	:param col_num: the number of columns
 11	:type col_num: int
 12	:param val: the default value to fill the matrix
 13	:type val: any (None by default)
 14	:return: matrix of rows_num x col_num
 15	:rtype: matrix
 16	"""
 17	matrix = []
 18	for i in range(col_num):
 19		col = [val] * row_num
 20		matrix.append(col)
 21	return matrix
 22
 23
 24def _check_index(matrix, row_no, col_no):
 25	"""
 26	check if row_no and col_no are in matrix bound
 27	
 28	:param matrix: the matrix to compute the size
 29	:type matrix: matrix
 30	:param rows_no: the index of row to check
 31	:type rows_no: int
 32	:param col_no: the index of column to check
 33	:type col_no: int
 34	:raise: IndexError if row_no or col_no are out of matrix bounds
 35	""" 
 36	row_max, col_max = size(matrix)
 37	if (row_no < 0 or row_no >= row_max) or (col_no < 0 or col_no >= col_max):
 38		raise IndexError("matrix index out of range")
 39	
 40	
 41def size(matrix):
 42	"""
 43	:param matrix: the matrix to compute the size
 44	:type matrix: matrix
 45	:return: the size of matrix (number of rows, number of cols)
 46	:rtype: typle of 2 int
 47	"""
 48	return len(matrix[0]), len(matrix)
 49
 50
 51def get_cell(matrix, row_no, col_no):
 52	"""
 53	:param matrix: the matrix 
 54	:type matrix: matrix
 55	:param rows_no: the row number
 56	:type rows_no: int
 57	:param col_no: the column number
 58	:type col_no: int
 59	:retrun: the content of cell corresponding to row_no x col_no
 60	:rtype: any
 61	"""
 62	_check_index(matrix, row_no, col_no)
 63	return matrix[col_no][row_no]
 64
 65
 66def set_cell(matrix, row_no, col_no, val):
 67	"""
 68	set the value val in cell specified by row_no x col_no
 69	
 70	:param matrix: the matrix to modify
 71	:type matrix: matrix
 72	:param row_no: the row number of cell to set
 73	:type rows_no: int
 74	:param col_no: the column number of cell to set
 75	:type col_no: int
 76	:param val: the value to set in cell 
 77	:type val: int
 78	"""
 79	_check_index(matrix, row_no, col_no)
 80	matrix[col_no][row_no] = val
 81
 82
 83def to_str(matrix):
 84	"""
 85	:param matrix: the matrix to compute the size
 86	:type matrix: matrix
 87	:return: a string representation of the matrix
 88	:rtype: str
 89	"""
 90	s = ""
 91	# by design all matrix cols have same size
 92	for row in zip(*matrix):
 93		cells = [str(cell) for cell in row]
 94		s += "\t".join(cells) + "\n"
 95	return s
 96
 97
 98def mult(matrix, val):
 99	"""
100	:param matrix: the matrix
101	:type matrix: matrix
102	:param val: the value to mult the matrix with
103	:type val: int
104	:return: a new matrix corresponding the scalar product of matrix * val
105	:rtype: matrix
106	"""
107	new_matrix = []
108	for col in matrix:
109		new_col = [cell * val for cell in col]
110		new_matrix.append(new_col)
111	return new_matrix
112
113
114def mult_inplace(matrix, val):
115	"""
116	compute the scalar product of a matrix and a value
117	do this operation in place
118
119	:param matrix: the matrix
120	:type matrix: matrix
121	:param val: the value to mult the matrix with
122	:type val: int
123	"""
124	for col in matrix:
125		for row_nb, cell in enumerate(col):
126			col[row_nb] = cell * val
127
128
129def get_row(matrix, row_no):
130	"""
131	:param matrix: the matrix to compute the size
132	:type matrix: matrix
133	:param rows_no: row number
134	:type rows_no: int
135	:return: the row of matrix corresponding to row_no
136	         a shallow copy of the row
137	:rtype: list
138	"""
139	_check_index(matrix, row_no, 0)
140	row_max, col_max = size(matrix)
141	row = []
142	for col_n in range(col_max):
143		row.append(get_cell(matrix, row_no, col_n))
144	return row
145	
146	
147def set_row(matrix, row_no, val):
148	"""
149	set all cells of row row_no with val
150	
151	:param matrix: the matrix to modify
152	:type matrix: matrix
153	:param row_no: the row number
154	:type row_no: int
155	:param val: the value to put in cells
156	:type val: any
157	"""
158	_check_index(matrix, row_no, 0)
159	row_max, col_max = size(matrix)
160	for col_n in range(col_max):
161		set_cell(matrix, row_no, col_n, val)
162
163
164def get_col(matrix, col_no):
165	"""
166	:param matrix: the matrix get row
167	:type matrix: matrix
168	:param col_no: the column number
169	:type col_no: int
170	:return: the column corresponding to col_no of matrix
171	         a shallow copy of the col
172	:rtype: list
173	"""
174	_check_index(matrix, 0, col_no)
175	col = matrix[col_no][:]
176	return col
177	
178	
179def set_col(matrix, col_no, val):
180	"""
181	set all cells of col col_no with val
182	
183	:param matrix: the matrix to compute the size
184	:type matrix: matrix
185	:param col_no: the column number
186	:type col_no: int
187	:param val: the value to put in cells
188	:type val: any
189	"""
190	_check_index(matrix, 0, col_no)
191	for row_n in range(matrix):
192		set_cell(matrix, row_n, col_no, val)
193
194
195def replace_col(matrix, col_no, col):
196	"""
197	replace column col_no with col
198	
199	:param matrix: the matrix to compute the size
200	:type matrix: matrix
201	:param col_no: the column number to replace
202	:type col_no: int
203	:param col: the list of values to use as replacement of column 
204	:type col: list
205	"""
206	row_max, col_max = size(matrix)
207	if len(col) != col_max:
208		raise RuntimeError("the size of col {0} does not fit to matrix size {1}x{2}".format(len(col),
209																						row_max,
210																						col_max))
211	_check_index(matrix, 0, col_no)
212	matrix[col_no] = col
213
214
215def replace_row(matrix, row_no, row):
216	"""
217	replace row row_no with row
218	
219	:param matrix: the matrix to compute the size
220	:type matrix: matrix
221	:param row_no: the column number
222	:type row_no: int
223	:param row: the list of value to use as replacement of row 
224	:type row: list
225	"""
226	row_max, col_max = size(matrix)
227	if len(row) != row_max:
228		raise RuntimeError("the size of row {0} does not fit to matrix size {1}x{2}".format(len(row),
229																							row_max,
230																							col_max))
231	_check_index(matrix, row_no, 0)
232	for col_no, value in enumerate(row):
233		set_cell(matrix, row_no, col_no, value)
234
235
236if __name__ == '__main__':
237	m = create(5, 3)
238	print(m)
239	set_cell(m, 0, 0, 1)
240	set_cell(m, 0, 2, 2)
241	set_cell(m, 4, 0, 12)
242	set_cell(m, 4, 2, 15)
243	print(to_str(m))
244	print("get row 0",  get_row(m, 0))
245	print("get col 0", get_col(m, 0))
246
247	m2 = create(3, 2, 4)
248	mult_inplace(m2, 2)
249	print(to_str(m2))

matrix.py .

Second implementation (bad variable naming, no documentation)

 1# matrix is implemented by list of list
 2def matrix_maker(ligne, col, val=None):
 3	m = []
 4	for i in range(ligne):
 5		c = [val] * col
 6		m.append(c)
 7	return m
 8
 9#---- functions that depends on the matrix srtructure 
10
11def matrix_size(m):
12	return len(m), len(m[0])
13
14def matrix_get(matrix, i, j):
15	_check_matindex(matrix, i, j)
16	return matrix[i][j]
17
18def matrix_set(matrix, i, j, val):
19	_check_matindex(matrix,i,j)
20	matrix[i][j] = val
21
22def to_str(m):
23	m_str = []
24	for row in m:
25		m_str.append('\t'.join([str(cell) for cell in row]))
26	m_str = '\n'.join(m_str)
27	return m_str
28
29
30
31#---- independant regarding matrix structure  
32def _check_matindex(matrix,i,j):
33	imax, jmax = matrix_size(matrix)
34	if (i < 0 or i >= imax) or (j < 0 or j >= jmax):
35		raise IndexError("matrix index out of range")
36
37
38def matrix_get_line(matrix, i):
39	_check_matindex(matrix,i,0)
40	im, jm = matrix_size(matrix)
41	line = []
42	for n in range(jm):
43		line.append(matrix_get(matrix, i, n))
44	return line
45
46
47def matrix_set_line(matrix, i, val):
48	_check_matindex(matrix,i,0)
49	im, jm = matrix_size(matrix)
50	for n in range(jm):
51		matrix_set(matrix, i, n, val)
52
53
54def matrix_get_col(matrix, j):
55	_check_matindex(matrix,0,j)
56	im, jm = matrix_size(matrix)
57	col = []
58	for n in range(im):
59		col.append(matrix_get(matrix, n, j))
60	return col
61
62
63def matrix_set_col(matrix, j, val):
64	_check_matindex(matrix,0,j)
65	im, jm = matrix_size(matrix)
66	for n in range(im):
67		matrix_set(matrix, n, j, val)
68	
69
70if __name__ == '__main__':
71	m = matrix_maker(5, 3)
72	matrix_set(m,0, 0, 1)
73	matrix_set(m,0, 2, 2)
74	matrix_set(m,4, 0, 12)
75	matrix_set(m,4, 2, 15)
76	print(to_str(m))
77	print("get line 0",  matrix_get_line(m, 0))
78	print("get col 0", matrix_get_col(m, 0))

matrix2.py .

Third implementation (dict {(row, col): value})

  1"""
  2Implementation of simple matrix
  3"""
  4
  5
  6def create(nb_rows, nb_cols, val=None):
  7    """
  8    :param nb_rows: the number of rows
  9    :type nb_rows: int
 10    :param nb_cols: the number of columns
 11    :type nb_cols: int
 12    :param val: the default value to fill the matrix
 13    :type val: any (None by default)
 14    :return: matrix of nb_rows x nb_cols
 15    :rtype: matrix
 16    """
 17    matrix = {}
 18    for i in range(nb_rows):
 19        for j in range(nb_cols):
 20            matrix[(i, j)] = val
 21    return matrix
 22
 23
 24import sys
 25major, minor = sys.version_info[:2]
 26if major < 3 or (major == 3 and minor < 7):
 27    raise NotImplementedError(
 28        "Implementation missing for this Python version:"
 29        "{}.{}".format(major, minor))
 30else:
 31    def size(matrix):
 32        """
 33        :param matrix: the matrix of which we want the size
 34        :type matrix: matrix
 35        :return: the size of matrix (number of rows, number of cols)
 36        :rtype: typle of 2 int
 37        """
 38        # Not robust, and needs a Python version where dicts preserve
 39        # key insertion order.
 40        # Only works because matrix was created
 41        # using a dict where the last inserted key corresponded
 42        # to the the last row and last column
 43        (last_row, last_col) = list(matrix.keys())[-1]
 44        return (last_row + 1, last_col + 1)
 45
 46
 47def _check_bounds(matrix, row, col):
 48    """
 49    Check whether row and col are compatible with the matrix size.
 50
 51    :param matrix: the matrix to check
 52    :type matrix: matrix
 53    :param row: the index of row to check
 54    :type row: int
 55    :param col: the index of column to check
 56    :type col: int
 57    :raise: IndexError if row or col are out of matrix bounds
 58    """
 59    (nb_rows, nb_cols) = size(matrix)
 60    if (row < 0 or row >= nb_rows) or (col < 0 or col >= nb_cols):
 61        raise IndexError("matrix index out of range")
 62
 63
 64def get_cell(matrix, row, col):
 65    """
 66    :param matrix: the matrix
 67    :type matrix: matrix
 68    :param row: the row number
 69    :type row: int
 70    :param col: the column number
 71    :type col: int
 72    :return: the content of cell corresponding to row x col
 73    :rtype: any
 74    """
 75    _check_bounds(matrix, row, col)
 76    return matrix[(row, col)]
 77
 78
 79def set_cell(matrix, row, col, val):
 80    """
 81    Set the value val in cell specified by row x col.
 82
 83    :param matrix: the matrix to modify
 84    :type matrix: matrix
 85    :param row: the row number of cell to set
 86    :type row: int
 87    :param col: the column number of cell to set
 88    :type col: int
 89    :param val: the value to set in cell
 90    :type val: int
 91    """
 92    _check_bounds(matrix, row, col)
 93    matrix[(row, col)] = val
 94
 95
 96def mult(matrix, val):
 97    """
 98    :param matrix: the matrix
 99    :type matrix: matrix
100    :param val: the value to mult the matrix with
101    :type val: int
102    :return: a new matrix corresponding the scalar product of matrix * val
103    :rtype: matrix
104    """
105    new_matrix = []
106    for (coords, value) in matrix.items():
107        new_matrix[coords] = value * val
108    return new_matrix
109
110
111def mult_inplace(matrix, val):
112    """
113    Compute the scalar product of a matrix and a value
114    do this operation in place
115
116    :param matrix: the matrix
117    :type matrix: matrix
118    :param val: the value to mult the matrix with
119    :type val: int
120    """
121    for (coords, value) in matrix.items():
122        matrix[coords] = value * val
123
124
125def get_row(matrix, row):
126    """
127    :param matrix: the matrix
128    :type matrix: matrix
129    :param row: row number
130    :type row: int
131    :return: the row of matrix corresponding to row
132    :rtype: list
133    """
134    _check_bounds(matrix, row, 0)
135    _, nb_cols = size(matrix)
136    row_values = []
137    for col in range(nb_cols):
138        row_values.append(get_cell(matrix, row, col))
139    return row_values
140
141
142def set_row(matrix, row, val):
143    """
144    set all cells of row row with val
145
146    :param matrix: the matrix to modify
147    :type matrix: matrix
148    :param row: the row number
149    :type row: int
150    :param val: the value to put in cells
151    :type val: any
152    """
153    _check_bounds(matrix, row, 0)
154    _, nb_cols = size(matrix)
155    for col in range(nb_cols):
156        set_cell(matrix, row, col, val)
157
158
159def get_col(matrix, col):
160    """
161    :param matrix: the matrix
162    :type matrix: matrix
163    :param col: the column number
164    :type col: int
165    :return: the column corresponding to col of matrix
166            a shallow copy of the col
167    :rtype: list
168    """
169    _check_bounds(matrix, 0, col)
170    nb_rows, _ = size(matrix)
171    col_values = []
172    for row in range(nb_rows):
173        col_values.append(get_cell(matrix, row, col))
174    return col_values
175
176
177def set_col(matrix, col, val):
178    """
179    set all cells of col col with val
180
181    :param matrix: the matrix to modify
182    :type matrix: matrix
183    :param col: the column number
184    :type col: int
185    :param val: the value to put in cells
186    :type val: any
187    """
188    _check_bounds(matrix, 0, col)
189    nb_rows, _ = size(matrix)
190    for row in range(nb_rows):
191        set_cell(matrix, row, col, val)
192
193
194def replace_col(matrix, col, col_values):
195    """
196    replace column col with col_values
197
198    :param matrix: the matrix to modify
199    :type matrix: matrix
200    :param col: the column number to replace
201    :type col: int
202    :param col_values: the list of values to use as replacement of column
203    :type col_values: list
204    """
205    nb_rows, nb_cols = size(matrix)
206    if len(col_values) != nb_rows:
207        raise RuntimeError(
208            f"the size of col_values {len(col_values)} does not fit "
209            f"matrix size {nb_rows} x {nb_cols}")
210    _check_bounds(matrix, 0, col)
211    for row in range(nb_rows):
212        set_cell(matrix, col, row, col_values[row])
213
214
215def replace_row(matrix, row, row_values):
216    """
217    replace row row with row_values
218
219    :param matrix: the matrix to modify
220    :type matrix: matrix
221    :param row: the column number
222    :type row: int
223    :param row: the list of value to use as replacement of row
224    :type row: list
225    """
226    nb_rows, nb_cols = size(matrix)
227    if len(row_values) != nb_cols:
228        raise RuntimeError(
229            f"the size of row_values {len(row_values)} does not fit "
230            f"matrix size {nb_rows} x {nb_cols}")
231    _check_bounds(matrix, row, 0)
232    for col in range(nb_cols):
233        set_cell(matrix, col, row, row_values[col])
234
235
236def to_str(matrix):
237    """
238    :param matrix: the matrix to represent as string
239    :type matrix: matrix
240    :return: a string representation of the matrix
241    :rtype: str
242    """
243    lines = []
244    nb_rows, nb_cols = size(matrix)
245    for row in range(nb_rows):
246        lines.append("\t".join([
247            str(val) for val in get_row(matrix, row)]))
248    return "\n".join(lines)
249
250
251if __name__ == '__main__':
252    m = create(5, 3)
253    print(m)
254    print(to_str(m))
255    set_cell(m, 0, 0, 1)
256    print(m)
257    print(to_str(m))
258    set_cell(m, 0, 2, 2)
259    print(m)
260    print(to_str(m))
261    set_cell(m, 4, 0, 12)
262    print(m)
263    print(to_str(m))
264    set_cell(m, 4, 2, 15)
265    print(m)
266    print(to_str(m))
267    print("get row 0",  get_row(m, 0))
268    print("get col 0", get_col(m, 0))
269
270    m2 = create(3, 2, 4)
271    mult_inplace(m2, 2)
272    print(to_str(m2))

matrix3.py .