81

私はニューロンのモデルを扱っています。私が設計している 1 つのクラスは、ニューロン (互いに接続された複数のコンパートメント) のトポロジー記述であるセル クラスです。多くのパラメーターがありますが、それらはすべて関連しています。次に例を示します。

軸索セグメントの数、先端の二線維化、体細胞の長さ、体細胞の直径、先端の長さ、分岐のランダム性、分岐の長さなど...全部で約 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
4

14 に答える 14

74

更新:このアプローチは特定のケースに適している可能性がありますが、間違いなく欠点があります。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")
于 2011-05-05T14:26:13.300 に答える
20

このアプローチには何も問題はないと思います。何かをモデル化するために 15 個のパラメーターが必要な場合は、15 個のパラメーターが必要です。また、適切なデフォルト値がない場合は、オブジェクトを作成するときに 15 個のパラメーターすべてを渡す必要があります。それ以外の場合は、デフォルトを設定し、後でセッターを介してまたは直接変更することができます。

別のアプローチは、特定の一般的な種類のニューロン (例) のサブクラスを作成し、特定の値に適切なデフォルトを提供するか、他のパラメーターから値を導出することです。

または、ニューロンの一部を別々のクラスにカプセル化し、これらの部分をモデル化する実際のニューロンに再利用することもできます。つまり、シナプス、軸索、細胞体などをモデル化するための個別のクラスを作成できます。

于 2011-05-05T14:26:22.897 に答える
7

非常に多くのパラメーターがあるということは、クラスがおそらくあまりにも多くのことを行っていることを示唆しています。

クラスをいくつかのクラスに分割し、それぞれがいくつかのパラメータを取ることをお勧めします。そうすれば、各クラスはより単純になり、それほど多くのパラメーターを使用しなくなります。

あなたのコードについてもっと知らなければ、どのように分割すべきか正確には言えません。

于 2011-05-05T15:01:33.920 に答える
7

おそらくPythonの「dict」オブジェクトを使用できますか? http://docs.python.org/tutorial/datastructures.html#dictionaries

于 2011-05-05T14:22:04.443 に答える
5

あなたが取り組んでいるもののいくつかのサンプルコードを提供できますか?あなたが何をしているのかを理解し、より早く助けを得るのに役立ちます。

クラスに渡す引数だけが長くなる場合は、すべてをに入れる必要はありません__init__。クラスの作成後にパラメータを設定するか、パラメータでいっぱいの辞書/クラスを引数として渡すことができます。

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])
于 2011-05-05T14:28:44.960 に答える
3

これは、デフォルトの辞書を繰り返し処理する他のソリューションと似ていますが、よりコンパクトな表記法を使用しています。

class MyClass(object):

    def __init__(self, **kwargs):
        self.__dict__.update(dict(
            arg1=123,
            arg2=345,
            arg3=678,
        ), **kwargs)
于 2014-03-21T18:07:42.837 に答える
3

あなたのコードを調べて、これらのパラメーターが互いにどのように関連しているのかわからないことに気付いた後 (神経科学に関する知識が不足しているため)、オブジェクト指向設計に関する非常に優れた本を紹介します。Steven F. Lott による Building Skills in Object Oriented Design は優れた読み物であり、オブジェクト指向プログラムをレイアウトする際に、あなたや他の誰にとっても役立つと思います。

これはクリエイティブ コモンズ ライセンスの下でリリースされているため、無料で使用できます。PDF 形式のリンクはhttp://homepage.mac.com/s_lott/books/oodesign/build-python/latex/BuildingSkillsinOODesign です。 pdf

あなたの問題は、クラスの全体的な設計に帰着すると思います。ごくまれに、初期化するために非常に多くの引数が必要になることがあります。ここでの回答のほとんどは、初期化の他の方法を詳しく説明していますが、多くの場合、クラスをより扱いやすく、扱いにくいクラスに分割できます。 .

于 2011-05-06T12:22:13.000 に答える
1

より詳細なユースケースを教えてください。おそらくプロトタイプパターンが機能するでしょう:

オブジェクトのグループにいくつかの類似点がある場合は、プロトタイプ パターンが役立つことがあります。ニューロンの 1 つの集団が、何らかの点で異なることを除いて、他の集団とまったく同じである場合がたくさんありますか? (つまり、少数の個別のクラスを使用するのではなく、互いにわずかに異なる多数のクラスを使用します。)

Python はクラスベースの言語ですが、Javascript のようなプロトタイプ ベースの言語でクラス ベースのプログラミングをシミュレートできるのと同じように、新しいオブジェクトを作成し、その ivar を親から移入する CLONE メソッドをクラスに与えることで、プロトタイプをシミュレートできます。渡されたキーワード パラメータが「継承された」パラメータをオーバーライドするように clone メソッドを記述し、次のような方法で呼び出すことができるようにします。

new_neuron = old_neuron.clone( branching_length=n1, branching_randomness=r2 )
于 2011-05-05T14:53:00.890 に答える
1

私はこの状況やこのトピックに対処する必要はありませんでした。あなたの説明は、設計を開発するときに、関連する追加のクラスがいくつかあることに気付くかもしれないことを意味します-コンパートメントが最も明白です。これらが独自のクラスとして出現する場合、パラメータの一部がこれらの追加クラスのパラメータになる可能性があります。

于 2011-05-05T15:32:19.603 に答える
0

パラメータのクラスを作成できます。

一連のパラメーターを渡す代わりに、1 つのクラスを渡します。

于 2011-05-05T14:21:06.487 に答える