Writing object oriented code in Python
20 janvier 2011 | Catégories: sage | View CommentsI am currently at Sage Days 28. Right now, there is a discussion about Analytic combinatorics in Sage and the new code written by Alex Raichev at tikcet #10519 was mentionned in the discussion. His code is a bunch of def python functions in a sage file. In Sage, code is written in object oriented way.
I am not an expert of the domain of analytic combinatorics, but I am coding oriented object Python since some time now. So I wrote a comment on the ticket gathering my thoughts to, I hope, help Alex to rewrite his set of functions into an oriented object structure. I copied the content of my comment below as it will be easier to share it.
Writing object oriented code : Finding the objects
How to structure a bunch of functions into classes? How to find which objects (python classes) you need? Here is the trick I personaly use. Consider each of your functions as a question you ask. Then, ask yourself to who are you asking each of your questions? Answers often gives you a good hint about the objects you need to implement. EXAMPLE. Suppose I code the function determinant. Question : To who do I ask the determinant?. Answer: To a matrix. Hence, matrix might be a good object (a python class) to implement.
You are the best person to answer to these questions. You might have 30 functions in your file, but only two or three different answers to the above question. Regroup the similar functions together: they will become the methods of a same class.
The sage file you uploaded starts with:
r""" [...] This code relates to analytic combinatorics. More specifically, it is a collection of functions designed to compute asymptotics of Maclaurin coefficients of certain classes of multivariate generating functions. The main function asymptotics() returns the first `N` terms of the asymptotic expansion of the Maclaurin coefficients `F_{n\alpha}` of the multivariate meromorphic function `F=G/H` as `n\to\infty`. It assumes that `F` is holomorphic in a neighborhood of the origin, that `H` is a polynomial, and that asymptotics in the direction of `\alpha` (a tuple of positive integers) are controlled by smooth or multiple points. [...] """
Reading only these lines, I imagine the following structure:
class HolomorphicMultivariateMeromorphicFunction(object): # Constructor of the object def __init__(self, F, G): #stores important information on the object as attributes of self self._F = F self._G = G def maclaurin_coefficients(self, n, alpha): r""" Return the maclaurin coefficients of self. INPUT: - ``alpha`` - tuple of positive integers OUTPUT: a python list of the first terms OR maybe an object of a class you implement if there exists pertinent questions to ask to it. """ #Do some computations based (I guess) on self._F and self._G intermediate_result1 = self.some_intermediate_computations_1() #Do more computations return something def asymptotics(self, N, alpha): r""" Returns the asymptotics of Maclaurin coefficients. """ #Do some computations based (I guess) on self._F and self._G intermediate_result2 = self.some_intermediate_computations_2() intermediate_result3 = self.some_intermediate_computations_3() return something #put here all the others functions needed to compute the asymptotics def some_intermediate_computations_1(self): pass def some_intermediate_computations_2(self): pass def some_intermediate_computations_3(self): pass ...
It also looks like you need some robustness somehow. But I need to know more information about what means
"that asymptotics in the direction of \(\alpha\) (a tuple of positive integers) are controlled by smooth or multiple points."
to decide whether this is checked at the creation of the object or before returning the asymptotics. But these hypothesis should be checked somewhere.
Hope this helps.
Cheers,
Sébastien Labbé, Montréal, (but currently at Sage Days 28, Orsay, France)