Dash回调中的Python重用函数

2024-04-29 08:03:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试在Python Dash框架中制作一个应用程序,它允许用户从列表中选择一个名称,并使用该名称填充另外两个输入字段。用户可以在六个位置从(相同)列表中选择名称,因此总共需要执行12次回调。我的问题是,如何使用单个函数定义来提供多个回调

正如我在其他地方看到的(here for example),人们在执行多个回调时重用相同的函数名,例如

@app.callback(
    Output('rp-mon1-health', 'value'),
    [Input('rp-mon1-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11

@app.callback(
    Output('rp-mon3-health', 'value'),
    [Input('rp-mon3-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11

@app.callback(
    Output('rp-mon1-health', 'value'),
    [Input('rp-mon1-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11

这是一个相同的重复吨,是坏的,如果有一个修复我需要实现以后。理想情况下,我可以做以下事情:

@app.callback(
    Output('rp-mon1-health', 'value'),
    [Input('rp-mon1-name', 'value')]
)
@app.callback(
    Output('rp-mon2-health', 'value'),
    [Input('rp-mon2-name', 'value')]
)
@app.callback(
    Output('rp-mon3-health', 'value'),
    [Input('rp-mon3-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11

然而,上述情况在前两种情况下没有回电,只有最后一种情况。我的代码如下

import json

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

monster_data = json.loads('''[{
    "name": "Ares Mothership",
    "health": 14,
    "transition": 2
  },{
    "name": "Cthugrosh",
    "health": 7,
    "transition": 3
  }]''')
monster_names = [{'label': m['name'], 'value': m['name']} for m in monster_data]
monster_names.append({'label': 'None', 'value': ''})

app = dash.Dash(__name__)


def gen_monster(player, i):
    name = 'Monster #%d:  ' % i
    id_gen = '%s-mon%d' % (player, i)
    output = html.Div([
        html.Label('%s Name   ' % name),
        html.Br(),
        dcc.Dropdown(
            options=monster_names,
            value='',
            id='%s-name' % id_gen
        ),
        html.Br(),
        html.Label('Health'),
        html.Br(),
        dcc.Input(value=11, type='number', id='%s-health' % id_gen),
        html.Br(),
        html.Label('Hyper Transition'),
        html.Br(),
        dcc.Input(value=6, type='number', id='%s-state' % id_gen),
    ], style={'border': 'dotted 1px black'})
    return output


app.layout = html.Div(children=[
    html.H1(children='Monsterpocalypse Streaming Stats Manager'),

    html.Div([
        html.Div([
            html.Label('Left Player Name: '),
            dcc.Input(value='Mark', type='text', id='lp-name'),
            gen_monster('lp', 1),
            html.Br(),
            gen_monster('lp', 2),
            html.Br(),
            gen_monster('lp', 3)
        ], style={'width': '300px'}),

        html.Br(),

        html.Div([
            html.Label('Right Player Name: '),
            dcc.Input(value='Benjamin', type='text'),
            gen_monster('rp', 1),
            html.Br(),
            gen_monster('rp', 2),
            html.Br(),
            gen_monster('rp', 3)
        ], style={'width': '300px'})
    ], style={'columnCount': 2}),

    html.Div(id='dummy1'),
    html.Div(id='dummy2')
])

@app.callback(
    Output('rp-mon1-health', 'value'),
    [Input('rp-mon1-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11


@app.callback(
    Output('rp-mon1-state', 'value'),
    [Input('rp-mon1-name', 'value')]
)
def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['transition']
    else:
        return 6


if __name__ == '__main__':
    app.run_server(debug=True)

Tags: namebridappinputreturnifvalue
2条回答

我也有同样的问题。只与输入和输出ID不同的回调负载。以下内容对我很有用(我将从我的代码中提供一个示例,但想法是一样的)

def rangeslider_tocalendar(output, input):
    @app.callback([Output(output, 'start_date'),
                   Output(output, 'end_date')],
                  [Input(input, 'value')])
    def repeated_callback(range_slider):
        cal_start = datetime.date.fromordinal(range_slider[0])
        cal_end = datetime.date.fromordinal(range_slider[1])
        return cal_start, cal_end

rangeslider_tocalendar('date-range', 'range-slider')

我将重复回调包装在函数rangeslider_tocalendar()中。然后我调用包装器函数并传入输入和输出ID。把意大利面从我的盘子里拿出来

你可以这样做:

def update_health(monster):
    if monster != '':
        relevant = [m for m in monster_data if m['name'] == monster]
        return relevant[0]['health']
    else:
        return 11


@app.callback(
    Output('rp-mon1-health', 'value'),
    [Input('rp-mon1-name', 'value')]
)
def monster_1_callback(*args, **kwargs):
    return update_health(*args, **kwargs)

@app.callback(
    Output('rp-mon2-health', 'value'),
    [Input('rp-mon2-name', 'value')]
)
def monster_2_callback(*args, **kwargs):
    return update_health(*args, **kwargs)


@app.callback(
    Output('rp-mon3-health', 'value'),
    [Input('rp-mon3-name', 'value')]
)
def monster_3_callback(*args, **kwargs):
    return update_health(*args, **kwargs)

现在,包含逻辑的函数只编写一次,其他函数都是简单的传递函数,不需要更新

相关问题 更多 >