Reputation: 135
I have some questions here. I'm trying to optimize my code and using line_profiler have found that the majority of my time is spent on class instantiation. Now here's a summary of what I'm trying to do and how I got here.
I have three classes: Template, Individual, Collective, set up roughly as such: (Not the actual code, but close enough to establish a more concrete idea of what I'm trying to do
class Template:
def __init__(self, param_boundaries):
self.param_boundaries = param_boundaries
class Individual(Template):
def __init__(self, i_params, template):
self.i_params = i_params
self.template = template
def method_example(self):
#modifies i_params based on self.template.param_boundaries
class Collective:
def __init__(self, n, template):
#creates n random Individuals using the Template
line_profiler shows that the biggest hurdle is the line self.template = template. And really, even if that wasn't the case it's taking up more memory than it needs to by saving the entirety of the template inside each Individual. My question is whether there's a way to simply reference the parameters passed into Template from Individual without having to save Template in the Individual dictionary.
A few things that might be useful: 1) Template will NOT be modified at all after it is instantiated. 2) Individuals do NOT communicate with each other 3) Collective only uses Template to generate Individuals 4) I am using Python 3.7
Please let me know if any additional information is required, or if this is a duplicate. To be quite honest, I don't really have the vocabulary to really search what it is that I am trying to do. I've tried to look for things before posting, but I haven't had any luck.
Upvotes: 0
Views: 943
Reputation: 110301
It seems like you had not understand enough of the concept of inheritance in Object Oriented approaches (and he way it works in Python) -
WHen you inherit from Template
your derived classes are a "Template" as well, besides being extended or refined in whatever code you write in the child-class bodies.
If "template" can be held in an attribute, then you are looking at class composition, which is generally easier to understand and work with than inheritance.
To proper use iheritance, however, any methods that you want to work well need to call the corresponding superclass method - In Python it is done with the demi-magic built-in super
- Your code would look like:
class Template:
def __init__(self, param_boundaries):
self.param_boundaries = param_boundaries
class Individual(Template):
def __init__(self, i_params, param_boundaries):
self.i_params = i_params
super().__init__(param_boundaries)
def method_example(self):
#modifies i_params based on self.template.param_boundaries
class Collective:
def __init__(self, n, param_boundaries):
super().__init__(param_boundaries)
#creates n random Individuals using the Template
So - your "Individual" and "Collective" classesm being at the same type a type of "Template" do have a .param_boundaries
attribute, which is created in the Template.__init__
function, to be reached using the super()...
call.
If you want both to have a "template" attribute which is a "Template" class instead, they should not inherit from Template
, and just be declared like:
class Individual:
def __init__(self, i_params, template):
self.i_params = i_params
self.template = template
Then it will work without any unexpected surprises.
As for the "hurdle" in self.template = template
line: that can't happen!
All Python is doing is creating a new reference to the already built object, and it is as trivial as it can be - if it is indeed listed on your profile as taking more resources than anything else, what you are seeing in the profiler is just noise (i.e. values so low that will vary from run to run, and if they do not, they still can't be made any faster in Python code), and there is nothing you can optimize there at all.
Upvotes: 1