具有太多参数的类:更好的devise策略?

我正在与神经元模型。 我正在devise的一个类是一个细胞类,这是一个神经元的拓扑描述(几个连接在一起的隔间)。 它有很多参数,但都是相关的,例如:

顶端双翅,体长,体细胞直径,顶端长度,分枝随机性,分枝长度等等…总共有15个参数!

我可以将所有这些设置为默认值,但我的类看起来很疯狂,几行参数。 这种事情也必须偶尔发生在别人身上,有没有一些明显的更好的方法来devise这个或者我做对了吗?

更新:正如你有些人问我已经附加了我的类的代码,正如你可以看到这个类有大量的参数(> 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 

尝试这种方法:

 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)) 

然后你可以像这样创build一个Neuron

 n = Neuron(apical_bifibrications="special value") 

我会说这种方法没有问题 – 如果你需要15个参数来build模,你需要15个参数。 如果没有合适的默认值,则在创build对象时必须传入全部15个参数。 否则,您可以设置默认值,稍后通过setter或直接更改。

另一种方法是为某些常见types的神经元(在你的例子中)创build子类,并为某些值提供良好的默认值,或从其他参数派生值。

或者你可以将神经元的一部分封装在单独的类中,并将这些部分重用于你build模的实际神经元。 也就是说,你可以编写独立的类来模拟突触,轴突,体细胞等。

你也许可以使用Python的“字典”对象? http://docs.python.org/tutorial/datastructures.html#dictionaries

有这么多的参数表明,class级可能做了太多的事情。

我build议你想把你的class级分成几个class级,每个class级都有你的一些参数。 这样,每个类都更简单,不会占用太多的参数。

不知道更多关于你的代码,我不能确切地说你应该如何分割它。

你能提供一些你正在处理的代码吗? 这将有助于了解你在做什么,并尽早得到帮助。

如果只是传递给类的参数使得它很长,则不__init__其全部放在__init__ 。 您可以在创build类之后设置参数,或者传递一个包含参数的字典/类作为参数。

 class MyClass(object): def __init__(self, **kwargs): arg1 = None arg2 = None arg3 = None for (key, value) in kwargs.iteritems(): if hasattr(self, key): setattr(self, key, value) if __name__ == "__main__": a_class = MyClass() a_class.arg1 = "A string" a_class.arg2 = 105 a_class.arg3 = ["List", 100, 50.4] b_class = MyClass(arg1 = "Astring", arg2 = 105, arg3 = ["List", 100, 50.4]) 

你可以为你的参数创build一个类。

相反,传递一堆参数,你传递一个类。

你能给一个更详细的用例吗? 也许一个原型模式将起作用:

如果在一组对象中有一些相似之处,原型模式可能会有所帮助。 你有很多情况下,一个神经元人口就像另一个神经元,除了在某种程度上有所不同吗? (即,而不是有less量的离散类,你有大量的类彼此略有不同)。

Python是一种基于分类的语言,但正如您可以在基于原型的语言(如Javascript)中模拟基于类的编程一样,您可以通过为您的类提供一个CLONE方法来模拟原型,从而创build一个新对象并从父级填充它的ivars。 编写克隆方法,以便传递给它的关键字参数覆盖“inheritance”的参数,所以你可以调用它的东西:

 new_neuron = old_neuron.clone( branching_length=n1, branching_randomness=r2 ) 

这与遍历默认字典的其他解决scheme类似,但它使用更简洁的表示法:

 class MyClass(object): def __init__(self, **kwargs): self.__dict__.update(dict( arg1=123, arg2=345, arg3=678, ), **kwargs) 

看起来您可以通过在LayerV构造函数之外构造诸如AxonSomaDendriticTree之类的对象来减less参数的数量,然后传递这些对象。

有些参数只用于构buildDendriticTree结构DendriticTree ,另外一些参数也用于其他地方,所以问题不大清楚,但我肯定会尝试这种方法。

我从来没有处理这个情况,或这个话题。 你的描述意味着我可以发现,在你开发devise的时候,有一些额外的类将会变得相关 – 车厢是最明显的。 如果这些确实以类的forms出现,那么很可能有一些参数成为这些附加类的参数。

看完你的代码,并意识到我不知道这些参数是如何相互关联的(因为我对神经科学的主题缺乏了解),我会给你一本关于面向对象devise的非常好的书。 Steven F. Lott的面向对象devise的build筑技巧是一个很好的阅读,我认为可以帮助你和任何其他人在布置面向对象的程序。

它是在Creative Commons License下发布的,所以可以免费使用,下面是PDF格式的链接http://homepage.mac.com/s_lott/books/oodesign/build-python/latex/BuildingSkillsinoodesign。; PDF格式

我认为你的问题归结为你的课程的整体devise。 有时候,尽pipe很less,你需要大量的参数来初始化,而且这里的大部分响应都有其他的初始化方法,但是在很多情况下,你可以把类分成更容易处理的类和更麻烦的类。

Interesting Posts