["python","oop"]
Class with too many parameters: better design strategy?

I am working with models of neurons. One class I am designing is a cell class which is a topological description of a neuron (several compartments connected together). It has many parameters but they are all relevant, for example: Number of axon segments, apical bifibrications, somatic length, somatic diameter, apical length, branching randomness, branching length and so on and so on... there are about 15 parameters in total! I can set all these to some default value but my class looks crazy with several lines for parameters. This kind of thing must happen occasionally to other people too, is there some obvious better way to design this or am I doing the right thing? As you can see this class has a huge number of parameters (>15) but they are all used and are necessary to define the topology of a cell. The problem essentially is that the physical object they create is very complex. How would experienced programmers do this differently to avoid so many parameters in the definition? class LayerV(__Cell): def __init__(self,somatic_dendrites=10,oblique_dendrites=10, somatic_bifibs=3,apical_bifibs=10,oblique_bifibs=3, L_sigma=0.0,apical_branch_prob=1.0, somatic_branch_prob=1.0,oblique_branch_prob=1.0, soma_L=30,soma_d=25,axon_segs=5,myelin_L=100, apical_sec1_L=200,oblique_sec1_L=40,somadend_sec1_L=60, ldecf=0.98): import random import math #make main the regions: axon=Axon(n_axon_seg=axon_segs) soma=Soma(diam=soma_d,length=soma_L) main_apical_dendrite=DendriticTree(bifibs= apical_bifibs,first_sec_L=apical_sec1_L, L_sigma=L_sigma,L_decrease_factor=ldecf, first_sec_d=9,branch_prob=apical_branch_prob) #make the somatic denrites somatic_dends=self.dendrite_list(num_dends=somatic_dendrites, bifibs=somatic_bifibs,first_sec_L=somadend_sec1_L, first_sec_d=1.5,L_sigma=L_sigma, branch_prob=somatic_branch_prob,L_decrease_factor=ldecf) #make oblique dendrites: oblique_dends=self.dendrite_list(num_dends=oblique_dendrites, bifibs=oblique_bifibs,first_sec_L=oblique_sec1_L, first_sec_d=1.5,L_sigma=L_sigma, branch_prob=oblique_branch_prob,L_decrease_factor=ldecf) #connect axon to soma: axon_section=axon.get_connecting_section() self.soma_body=soma.body soma.connect(axon_section,region_end=1) #connect apical dendrite to soma: apical_dendrite_firstsec=main_apical_dendrite.get_connecting_section() soma.connect(apical_dendrite_firstsec,region_end=0) #connect oblique dendrites to apical first section: for dendrite in oblique_dends: apical_location=math.exp(-5*random.random()) #for now connecting randomly but need to do this on some linspace apsec=dendrite.get_connecting_section() apsec.connect(apical_dendrite_firstsec,apical_location,0) #connect dendrites to soma: for dend in somatic_dends: dendsec=dend.get_connecting_section() soma.connect(dendsec,region_end=random.random()) #for now connecting randomly but need to do this on some linspace #assign public sections self.axon_iseg=axon.iseg self.axon_hill=axon.hill self.axon_nodes=axon.nodes self.axon_myelin=axon.myelin self.axon_sections=[axon.hill]+[axon.iseg]+axon.nodes+axon.myelin self.soma_sections=[soma.body] self.apical_dendrites=main_apical_dendrite.all_sections+self.seclist(oblique_dends) self.somatic_dendrites=self.seclist(somatic_dends) self.dendrites=self.apical_dendrites+self.somatic_dendrites self.all_sections=self.axon_sections+[self.soma_sections]+self.dendrites
This approach may be suited in your specific case, but it definitely has its downsides, see is kwargs an antipattern? Try this approach: class Neuron(object): def __init__(self, **kwargs): prop_defaults = { "num_axon_segments": 0, "apical_bifibrications": "fancy default", ... } for (prop, default) in prop_defaults.iteritems(): setattr(self, prop, kwargs.get(prop, default)) You can then create a Neuron like this: n = Neuron(apical_bifibrications="special value")