参数过多的类:更好的设计策略?
我正在研究神经元模型。我正在设计一个叫做“细胞类”的东西,它是神经元的拓扑描述(就是几个部分连接在一起)。这个类有很多参数,但每一个都很重要,比如:
轴突段的数量、顶端分叉、细胞体的长度、细胞体的直径、顶端的长度、分叉的随机性、分叉的长度等等……总共有大约15个参数!
我可以把这些参数都设置成一些默认值,但我的类看起来就像一团乱麻,参数行数太多了。这种情况应该也会发生在其他人身上,有没有什么更好的设计方法,还是我这样做是对的呢?
更新:有些人问我,所以我附上了我的类的代码。正如你们所看到的,这个类有很多参数(超过15个),但它们都是必要的,用来定义一个细胞的拓扑结构。问题的关键在于,它们创建的物理对象非常复杂。我还附上了一张这个类生成的对象的图片。经验丰富的程序员会如何做得不同,以避免在定义中使用这么多参数呢?
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
14 个回答
你可以试试用Python的“字典”对象吗?
这里有个链接,可以了解更多关于字典的信息:http://docs.python.org/tutorial/datastructures.html#dictionaries
我觉得这种做法没有问题。如果你需要15个参数来描述某个东西,那就需要15个参数。如果没有合适的默认值,那在创建对象的时候就得把这15个参数都传进去。否则,你可以先设置一个默认值,之后再通过设置器或者直接修改来改变它。
另一种方法是为某些常见类型的神经元(在你的例子中)创建子类,并为某些值提供好的默认值,或者根据其他参数来推导这些值。
你也可以把神经元的一部分封装到单独的类里,然后在你建模的实际神经元中重用这些部分。比如,你可以为建模突触、轴突、细胞体等写不同的类。
更新:这种方法可能适合你的具体情况,但它确实有一些缺点,具体可以查看 kwargs是否是一种反模式?
可以尝试这种方法:
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))
然后你可以这样创建一个 Neuron
:
n = Neuron(apical_bifibrications="special value")