Выполнение функций в словаре переключателей
Я столкнулся с проблемой при установке всех модулей, которые я разработал в основную программу. Созданный словарь коммутаторов можно увидеть ниже:
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)
Здесь вы сначала получите функцию, которую хотите вызвать, с соответствующими аргументами и назовите ее.