Class with too many parameters: better design strategy?

Да, PHP_EOL якобы используется для нахождения символа новой строки кросс-платформенно-совместимым способом, таким образом, он обрабатывает проблемы DOS/Unix.

Примечание, что PHP_EOL представляет endline символ для текущий система. Например, это не найдет Windows endline, когда выполняется в подобной Unix системе.

69
задан NorthCat 25 June 2015 в 09:43
поделиться

6 ответов

Я бы сказал, что в этом подходе нет ничего плохого - если вам нужно 15 параметров для моделирования чего-либо, вам нужно 15 параметров. И если нет подходящего значения по умолчанию, вы должны передать все 15 параметров при создании объекта. В противном случае вы можете просто установить значение по умолчанию и изменить его позже с помощью установщика или напрямую.

Другой подход заключается в создании подклассов для некоторых распространенных типов нейронов (в вашем примере) и обеспечении хороших значений по умолчанию для определенных значений или получения значений из других параметров.

Или вы можете заключить части нейрона в отдельные классы и повторно использовать эти части для реальных нейронов, которые вы моделируете. То есть вы могли бы написать отдельные классы для моделирования синапса, аксона, сомы и т. Д.

16
ответ дан 24 November 2019 в 13:51
поделиться

Наличие стольких параметров говорит о том, что класс, вероятно, делает слишком много вещей.

Я предлагаю вам разделить ваш класс на несколько классов, каждый из которых принимает некоторые из ваших параметров. Таким образом, каждый класс проще и не будет принимать столько параметров.

Не зная больше о вашем коде, я не могу точно сказать, как вы должны его разделить.

6
ответ дан 24 November 2019 в 13:51
поделиться

Не могли бы вы привести пример кода того, над чем вы работаете? Это помогло бы получить представление о том, что вы делаете, и получить помощь раньше.

Если только аргументы, которые вы передаете классу, делают его длинным, вам не нужно помещать все это в __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])
5
ответ дан 24 November 2019 в 13:51
поделиться

Мне никогда не приходилось сталкиваться с этой ситуацией или этой темой. Ваше описание подразумевает для меня, что при разработке дизайна вы можете обнаружить, что есть ряд дополнительных классов, которые станут актуальными - купе является наиболее очевидным. Если они появляются как классы сами по себе, вполне вероятно, что некоторые из ваших параметров станут параметрами этих дополнительных классов.

1
ответ дан 24 November 2019 в 13:51
поделиться

Это похоже на другие решения, которые перебирают словарь по умолчанию, но использует более компактную запись:

class MyClass(object):

    def __init__(self, **kwargs):
        self.__dict__.update(dict(
            arg1=123,
            arg2=345,
            arg3=678,
        ), **kwargs)
2
ответ дан 24 November 2019 в 13:51
поделиться

На мой взгляд, в вашем случае самое простое решение - передать объекты более высокого порядка в качестве параметра.

Например, в вашем __init__ у вас есть DendriticTree, который использует несколько аргументов из вашего основного класса LayerV:

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
)

Вместо передачи этих 6 аргументов вашему LayerV вы бы передавали объект DendriticTree напрямую (сохраняя 5 аргументов).

Возможно, вы хотите, чтобы эти значения были доступны везде, поэтому вам придется сохранить это DendriticTree:

class LayerV(__Cell):
    def __init__(self, main_apical_dendrite, ...):
        self.main_apical_dendrite = main_apical_dendrite        

Если вы хотите иметь значение по умолчанию, вы можете иметь:

class LayerV(__Cell):
    def __init__(self, main_apical_dendrite=None, ...):
        self.main_apical_dendrite = main_apical_dendrite or DendriticTree()

Таким образом, вы делегируете то, что должно быть по умолчанию DendriticTree, классу, посвященному этому вопросу, вместо того, чтобы иметь эту логику в классе более высокого порядка, чем LayerV.

Наконец, когда вам нужно получить доступ к apical_bifibs, который вы использовали для перехода к LayerV, вы просто получаете к нему доступ через self.main_apical_dendrite.bifibs.

В общем, даже если создаваемый вами класс не является четкой композицией из нескольких классов, ваша цель - найти логический способ разделения ваших параметров. Не только для того, чтобы сделать ваш код чище, но и для того, чтобы помочь людям понять, для чего эти параметры будут использоваться. В крайних случаях, когда вы не можете их разделить, я думаю, что вполне нормально иметь класс с таким количеством параметров. Если нет четкого способа разделения аргументов, вы, вероятно, в конечном итоге получите что-то еще менее ясное, чем список из 15 аргументов.

Если вы чувствуете, что создание класса для группировки параметров является излишним, то вы можете просто использовать collections.namedtuple , который может иметь значения по умолчанию, как , показанное здесь . [1 125]

0
ответ дан 24 November 2019 в 13:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: