[python] 매개 변수가 너무 많은 클래스 : 더 나은 설계 전략?

저는 뉴런 모델로 작업하고 있습니다. 제가 디자인하고있는 클래스 중 하나는 뉴런의 토폴로지 설명 인 셀 클래스입니다 (여러 구획이 서로 연결되어 있음). 매개 변수가 많지만 모두 관련이 있습니다. 예를 들면 다음과 같습니다.

축삭 분절의 수, 정점 bifibrications, 체세포 길이, 체체 직경, 정점 길이, 분기 임의성, 분기 길이 등 … 총 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



답변

업데이트 : 이 접근 방식은 특정 경우에 적합 할 수 있지만 확실히 단점 이 있습니다. 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")


답변

이 접근 방식에는 아무런 문제가 없다고 말하고 싶습니다. 무언가를 모델링하기 위해 15 개의 매개 변수가 필요하다면 15 개의 매개 변수가 필요합니다. 적절한 기본값이 없으면 개체를 만들 때 15 개의 매개 변수를 모두 전달해야합니다. 그렇지 않으면 기본값을 설정하고 나중에 setter를 통해 또는 직접 변경할 수 있습니다.

또 다른 접근 방식은 특정 일반적인 종류의 뉴런 (예 :)에 대한 하위 클래스를 만들고 특정 값에 대해 좋은 기본값을 제공하거나 다른 매개 변수에서 값을 파생하는 것입니다.

또는 뉴런의 일부를 별도의 클래스로 캡슐화하고 이러한 부분을 모델링하는 실제 뉴런에 재사용 할 수 있습니다. 즉, 시냅스, 축삭, 소마 등을 모델링하기위한 별도의 클래스를 작성할 수 있습니다.


답변

Python “dict”객체를 사용할 수 있습니까?
http://docs.python.org/tutorial/datastructures.html#dictionaries


답변

매개 변수가 너무 많으면 클래스가 너무 많은 일을하고 있음을 나타냅니다.

클래스를 여러 클래스로 나누고 각 클래스는 몇 가지 매개 변수를 사용하는 것이 좋습니다. 이렇게하면 각 클래스가 더 간단하고 많은 매개 변수를 사용하지 않습니다.

코드에 대해 더 많이 알지 못하면 코드를 어떻게 분할해야하는지 정확히 말할 수 없습니다.


답변

Axon, Soma및 같은 객체를 구성하여 인수 수를 줄일 수있는 것 같습니다.DendriticTree LayerV 생성자의 외부, 대신 그 객체를 전달합니다.

매개 변수 중 일부는 예를 들어 구성에만 사용되며 DendriticTree다른 매개 변수는 다른 장소에서도 사용되므로 문제는 명확하지 않지만 확실히 시도해 볼 것입니다.


답변

작업중인 작업에 대한 예제 코드를 제공 할 수 있습니까? 당신이하는 일에 대한 아이디어를 얻고 더 빨리 도움을받는 것이 도움이 될 것입니다.

클래스에 전달하는 인수가 길어지면 모든 것을 __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])


답변

여러분의 코드를 살펴보고 그 매개 변수가 서로 어떤 관련이 있는지 전혀 모르겠다는 것을 깨달은 후에 (신경 과학 주제에 대한 지식이 부족하기 때문에 혼자서) 객체 지향 설계에 대한 아주 좋은 책을 알려 드리겠습니다. Steven F. Lott의 Object Oriented Design의 Building Skills in Object Oriented Design은 훌륭한 읽기이며 저는 여러분과 다른 사람이 객체 지향 프로그램을 배치하는 데 도움이 될 것이라고 생각합니다.

크리에이티브 커먼즈 라이선스에 따라 출시되었으므로 무료로 사용할 수 있습니다. 여기에 PDF 형식의 링크가 있습니다 . http://homepage.mac.com/s_lott/books/oodesign/build-python/latex/BuildingSkillsinOODesign. pdf

나는 당신의 문제가 수업의 전반적인 디자인으로 귀결된다고 생각합니다. 매우 드물지만 초기화를 위해 많은 인수가 필요하며 여기에있는 대부분의 응답에는 다른 초기화 방법이 자세히 설명되어 있지만 많은 경우 클래스를 처리하기 더 쉽고 덜 성가신 클래스로 나눌 수 있습니다. .