我正在使用 Python dash,并且有一个回调每 1000 毫秒更新一次并输出一个虚拟值(比如回调运行的次数)。
我想在按下按钮时更改回调的输出值。
我找到了2个选择:
# Using 2 callbacks
from dash import dash, dcc, html, Input, Output, State
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Interval(id="interval", interval=1000),
html.Button("Press", id="button"),
html.Div(id="output")
]
)
@app.callback(
Output("output", "children"),
[Input("interval", "n_intervals")],
[State("button", "n_clicks")]
)
def update_output(n_intervals, n_clicks):
if n_clicks == 0:
return f"Interval: {n_intervals} - Button not pressed"
if n_clicks != 0:
return f"Interval: {n_intervals} - Button pressed"
@app.callback(
Output("button", "n_clicks"),
[Input("output", "children")]
)
def reset_button(n):
return 0
if __name__ == "__main__":
app.run_server(debug=True)
# Using a hidden div
from dash import dash, dcc, html, Input, Output, State, callback_context
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Interval(id="interval", interval=1000),
html.Button("Press", id="button"),
html.Div(id="output"),
html.Div(id="hidden-div", style={"display": "none"}, children="0")
]
)
@app.callback(
[Output("output", "children"), Output("hidden-div", "children")],
[Input("interval", "n_intervals"), Input("button", "n_clicks")],
[State("hidden-div", "children")]
)
def update_output(n_intervals, n_clicks, hidden_clicks):
ctx = callback_context
if ctx.triggered[0]["prop_id"] == "button.n_clicks":
return f"Interval: {n_intervals} - Button pressed", hidden_clicks
else:
return f"Interval: {n_intervals} - Button not pressed", hidden_clicks
if __name__ == "__main__":
app.run_server(debug=True)
最好的解决方案是什么?
如果我必须选择,我会说第一个,因为它比第二个更容易阅读。 但第二个想法并没有那么糟糕。事实上,我想提出一个替代方案。 ctx 有一个属性(称为trigger_id),它是触发回调的人的值(字符串)(官方文档)。所以我将代码重写如下:
@app.callback(
Output("output", "children"),
[Input("interval", "n_intervals"),
Input("button", "n_clicks")]
)
def update_output(n_intervals, n_clicks):
if ctx.triggered_id == 'interval':
return f"Interval: {n_intervals} - Button not pressed"
return f"Interval: {n_intervals} - Button pressed"
正如您所看到的,您减少了函数数量并提高了性能,因为在第一个代码中您使用了 2 个“if”语句,而在第二个代码中您访问了一个列表(使用触发的_id 您只进行了访问到字符串)。
但是,Dash 建议您创建清晰的函数,不要在单个函数中创建太多的输入和输出。但有时也有特殊情况,就像这里(我认为)。