Выполнение функций в словаре переключателей

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

def Tank_Shape_Calcs(Tank_Shape, level, area, dish, radius, length, Strapping_Table, Tank_Number):

    switcher = {
        0: vertical.Vertical_Tank(level, area),
        1: horiz.Horiz_Cylinder_Dished_Ends(dish, radius, level, length),
        2: strapping.Calc_Strapped_Volume(Strapping_Table, level),
        3: poly.Fifth_Poly_Calcs(Tank_Number)
    }
    return switcher.get(Tank_Shape, "ERROR: Tank type not valid")

Форма резервуара устанавливается в основной файл в петле для каждого из резервуаров. Первый танк имеет Tank_Shape = 2, поэтому я ожидаю, что он выполнит функцию Calc_Strapped_Volume().

Я попытался проверить его, и функция переключателя определенно читает Tank_Shape как 2. Также, если я изменил функции на строки, он напечатает правильную строку.

Проблема заключается в том, что функции, как представляется, выполняются последовательно, пока не будет вызвана правильная функция. Это приводит к ошибкам, так как данные, которые я использую, будут работать только с правильной функцией.

Есть ли способ выполнить правильную функцию?

Ответы

Ответ 1

Все ваши функции выполняются при создании словаря, а не при доступе к ключу.

Вам нужно использовать lambda (без каких-либо параметров, они уже известны), чтобы убедиться, что функция вызывается только при необходимости:

switcher = {
    0: lambda : vertical.Vertical_Tank(level, area),
    1: lambda : horiz.Horiz_Cylinder_Dished_Ends(dish, radius, level, length),
    2: lambda : strapping.Calc_Strapped_Volume(Strapping_Table, level),
    3: lambda : poly.Fifth_Poly_Calcs(Tank_Number)
}

затем вызовите, когда вы вернетесь, с сообщением об ошибке как лямбда, который возвращает его:

return switcher.get(Tank_Shape, lambda : "ERROR: Tank type not valid")()

Ответ 2

Как отмечено, функции будут вызваны во время построения словаря. Кроме того, есть две другие проблемы, которые я вижу здесь:

  • Переопределяя switcher во время каждого вызова функции Tank_Shape_Calcs, это, как правило, не очень хорошая идея.
  • Требуется передать все аргументы (из-за их определения как позиционеров), когда может понадобиться только несколько из них, поэтому мы имеем *args:-)

Если мое понимание того, что вы делаете, правильное, я бы переключил переключатель вне функции, как отображение объекта Tank_Shape в function:

switcher = {
    0: vertical.Vertical_Tank,
    1: horiz.Horiz_Cylinder_Dished_Ends,
    2: strapping.Calc_Strapped_Volume,
    3: poly.Fifth_Poly_Calcs
}

Затем определите Tank_Shape_Calcs, чтобы взять лишние аргументы как набор с *args:

def Tank_Shape_Calcs(Tank_Shape, *args):
    return switcher.get(Tank_Shape, lambda *_: "ERROR: Tank type not valid")(*args)

и вызовите вашу функцию после .get ting it.

Это также снимает трюк Jean, чтобы определить lambda в .get, но делает это с помощью *_, чтобы позволить ему вызываться со многими аргументами (которые, следовательно, игнорируются).

Ответ 3

Что вы делаете в своем коде, создается словарь с целыми ключами (0-3) и результаты функции как значения. Следовательно, вы сначала вызываете все функции, а затем получаете доступ к возвращаемым значениям этих функций. Я бы изменил ваш код следующим образом:

def Tank_Shape_Calcs(Tank_Shape, level, area, dish, radius, length, Strapping_Table, Tank_Number):
    switcher = {
        0: (vertical.Vertical_Tank, (level, area)),
        1: (horiz.Horiz_Cylinder_Dished_Ends, (dish, radius, level, length)),
        2: (strapping.Calc_Strapped_Volume, (Strapping_Table, level)),
        3: (poly.Fifth_Poly_Calcs, (Tank_Number,))
    }
    func, args = switcher.get(Tank_Shape, (None, None))
    if func is not None: 
        return func(*args)

Здесь вы сначала получите функцию, которую хотите вызвать, с соответствующими аргументами и назовите ее.