(数据科学学习手札104)Python+Dash快速web应用开发——回调交互篇(上)

费弗里 2021-01-22 20:05:03
学习 数据 科学 学学 科学学


本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

1 简介

这是我的系列教程Python+Dash快速web应用开发的第三期,在前两期的教程中,我们围绕什么是Dash,以及如何配合方便好用的第三方拓展dash-bootstrap-components来为我们的Dash应用设计布局展开了非常详细的介绍。

Dash最吸引我的地方在于其高度封装了react.js,使得我们无需编写js语句,纯Python编程就可以实现浏览器前端与后端计算之间常规的异步通信,从而创造出功能强大的交互式web应用。

图1

从今天的文章开始,我就将开始带大家走进Dash的核心内容——回调

2 Dash中的基础回调

2.1 最基础的回调

Dash中的回调callback)是以装饰器的形式,配合自编回调函数,实现前后端异步通信交互,这句话可能不太好理解,我们从一个简单的例子出发来认识Dash中的回调

app1.py

import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value',
placeholder='请输入些东西'),
width=12),
dbc.Col(dbc.Label(id='output-value'),
width=12)
]
)
]
)
]
)
# 对应app实例的回调函数装饰器
@app.callback(
Output('output-value', 'children'),
Input('input-value', 'value')
)
def input_to_output(input_value):
'''
简单的回调函数
'''
return input_value
if __name__ == '__main__':
app.run_server()

先来看看app1的交互效果:

图2

下面我们来分解上面的代码,梳理一下要构造一个具有实际交互功能的Dash应用需要做什么:

  • 确定输入与输出部件

一个可交互的系统一定是有输入输出的,我们开头导入的InputOutput对象,他们分别扮演着输入者输出者两种角色,其各自的第一个参数component_id用于联动前端部分定义的部件。

我们在前面定义前端部件时,为dbc.Input对应的输入框设置了id='input-value',为dbc.Label对应的文字输出设置了id='output-value',让它们作为第一个参数可以被Input()Output()唯一识别出来。

  • 确定输入与输出内容

在确定了输入者输出者之后,更重要的是为告诉Dash需要监听什么输入,响应什么输出,这就要用到第二个参数component_property

它与对应的前端部件有关,譬如我们的dbc.Input()输入框,其被输入的内容都存在value属性中,而children属性是dbc.Label以及绝大多数html部件的第一个参数,这样我们就确定了输入输出内容。

  • 装饰回调函数

app.callback()装饰器按照规定的先Output()Input()的顺序传入相应对象,而既然是装饰器,自然需要配合自定义回调函数使用。

我们的input_to_output()就是对应的回调函数,其参数与装饰器中的Input()对应,而函数内部则用来定义计算处理过程。

最后return的对象则对应Output()

# 对应app实例的回调函数装饰器
@app.callback(
Output('output-value', 'children'),
Input('input-value', 'value')
)
def input_to_output(input_value):
'''
简单的回调函数
'''
return input_value

通过上面这样的结构,我们得以纯Python“寥寥数语”实现了交互功能,赋予我们编写任意功能Dash应用的能力。

2.2 同时设置多个Input()与Output()

在上一小节中我们介绍的是最基本的单输入 -> 单输出回调模式,很多时候我们需要更复杂的回调模式,譬如下面的例子:

app2.py

import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value1'), width=3),
dbc.Col(html.P('+'), width=1),
dbc.Col(dbc.Input(id='input-value2'), width=3),
],
justify='start'
),
html.Hr(),
dbc.Label(id='output-value')
]
)
]
)
@app.callback(
Output('output-value', 'children'),
Input('input-value1', 'value'),
Input('input-value2', 'value')
)
def input_to_output(input_value1, input_value2):
try:
return float(input_value1) + float(input_value2)
except:
return '请输入合法参数!'
if __name__ == '__main__':
app.run_server()
图3

这里我们的Input()对象不止一个,在Output()对象之后依次传入(也可以把所有Input()对象包在一个列表中传入),其顺序对应后面回调函数的参数顺序,从而实现了多个输入值的一一对应。

同样的,Output()也可以有多个:

app3.py

import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-lastname'), width=3),
dbc.Col(html.P('+'), width=1),
dbc.Col(dbc.Input(id='input-firstname'), width=3),
],
justify='start'
),
html.Hr(),
dbc.Label(id='output1'),
html.Br(),
dbc.Label(id='output2')
]
)
]
)
@app.callback(
[Output('output1', 'children'),
Output('output2', 'children')],
[Input('input-lastname', 'value'),
Input('input-firstname', 'value')]
)
def input_to_output(lastname, firstname):
try:
return '完整姓名:' + lastname + firstname, f'姓名长度为{len(lastname+firstname)}'
except:
return '等待输入...', '等待输入...'
if __name__ == '__main__':
app.run_server()
图4

可以看到不管是多个Output()还是Input(),只需要嵌套在列表中即可。

2.3 利用State()实现惰性交互

很多情况下,如果我们的回调函数计算过程时间开销较大,那么像前面介绍的仅靠Input()Output()实现的前后端通信会很频繁,因为监听到的所有输入部件对应属性值只要略一改变,就会触发回调。

为了解决这类问题,Dash中设计了State()对象,我们可以利用State()替换Input()来绑定对应的输入值,再将一些需要主动触发的譬如dbc.Button()按钮部件的属性n_clicks,作为Input()对象进行绑定。

让我们通过下面的例子更好的理解它的作用:

app4.py

import dash
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
app = dash.Dash(
__name__,
external_stylesheets=['css/bootstrap.min.css']
)
app.layout = html.Div(
[
html.Br(),
html.Br(),
html.Br(),
dbc.Container(
[
dbc.Row(
[
dbc.Col(dbc.Input(id='input-value'),
width=4),
dbc.Col(dbc.Button('小写转大写',
id='state-button',
n_clicks=0),
width=4),
dbc.Col(dbc.Label(id='output-value',
style={'padding': '0',
'margin': '0',
'line-height': '38px'}),
width=4)
],
justify='start'
)
]
)
]
)
@app.callback(
Output('output-value', 'children'),
Input('state-button', 'n_clicks'),
State('input-value', 'value')
)
def input_to_output(n_clicks, value):
if n_clicks:
return value.upper()
if __name__ == '__main__':
app.run_server()
图5

可以看到,装饰器中按照Output()Input()State()的顺序传入各个对象后,我们的Button()部件的n_clicks参数记录了对应的按钮被点击了多少次,初始化我们设置其为0,之后每次等我们输入完单词,主动去点击按钮从而增加其被点击次数记录时,回调函数才会被触发,这样就方便了我们的很多复杂应用场景~


以上就是本期的全部内容,欢迎在评论区与我进行讨论~

版权声明
本文为[费弗里]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/feffery/p/14313103.html

  1. python中hmac模块的使用
  2. Python crawler_ Garbage man idle fish crawler turn crawler data integration self use second hand rapid response garbage collection platform_ 3 (with continuous source update)
  3. Using Python javaserialization tools module to generate 8u20 gadget
  4. The basic syntax of Python
  5. The use of HMAC module in Python
  6. 攻防世界web进阶区Web_python_block_chain详解
  7. Attack and defense world web advanced zone Web_ python_ block_ Details of chain
  8. pandas DataFrame的新增行列,修改、删除、筛选、判断元素以及转置操作
  9. Add rows and columns, modify, delete, filter, judge elements and transpose operations in pandas dataframe
  10. pandas DataFrame的新增行列,修改、删除、筛选、判断元素以及转置操作
  11. Add rows and columns, modify, delete, filter, judge elements and transpose operations in pandas dataframe
  12. 虚言妙诀终虚见,面试躬行是致知,Python技术面试策略与技巧实战记录
  13. The interview practice is knowledge, python technology interview strategy and skills of the actual record
  14. 用tqdm和rich为固定路径和目标的python算法代码实现进度条
  15. Using tqdm and rich as the fixed path and target of Python algorithm code to realize the progress bar
  16. 我来记笔记啦-Django开发流程与配置
  17. Let me take notes - Django development process and configuration
  18. python数据类型的强制转换
  19. Django报错:'Key 'id' not found in 'xxx'. Choices are: xxx'
  20. Python400集大型视频,从正确的方向出发学习,全套完整送给大家
  21. Mandatory conversion of Python data type
  22. Django reported an error: 'key' ID 'not found in' xxx '. Choices are: xxx'
  23. Python 400 sets of large video, starting from the right direction to learn, a complete set to you
  24. 只需十四步:从零开始掌握Python机器学习(附资源)
  25. Just 14 steps: Master Python machine learning from scratch (resources attached)
  26. Python|文件读写
  27. 安利一个Python界神奇得网站
  28. Python | file reading and writing
  29. Amway is a marvelous website in Python world
  30. 第二热门语言:从入门到精通,Python数据科学简洁教程
  31. The second popular language: from introduction to mastery, python data science concise tutorial
  32. 以我的亲身经历,聊聊学python的流程,同时推荐学python的书
  33. With my own experience, I'd like to talk about the process of learning Python and recommend books for learning python
  34. 以我的亲身经历,聊聊学python的流程,同时推荐学python的书
  35. With my own experience, I'd like to talk about the process of learning Python and recommend books for learning python
  36. Django url 路由匹配过程
  37. Django URL routing matching process
  38. 强者一出,谁与争锋?与Python相比,C++的运行速度究竟有多快?
  39. Who will fight against the strong? How fast is C + + running compared with Python?
  40. python 学习体会
  41. Experience of learning Python
  42. python7、8章
  43. Chapter 7 and 8 of Python
  44. python bool和str转换
  45. python——循环(for循环、while循环)及练习
  46. python变量和常量命名、注释规范
  47. python自定义异常捕获异常处理异常
  48. python 类型转换与数值操作
  49. python 元组(tuple)和列表(list)区别
  50. 解决python tkinter 与 sleep 延迟问题
  51. python字符串截取操作
  52. Python bool and STR conversion
  53. Python -- loop (for loop, while loop) and Practice
  54. Specification for naming and annotating variables and constants in Python
  55. Python custom exception capture exception handling exception
  56. Python type conversion and numerical operation
  57. The difference between tuple and list in Python
  58. Solve the delay problem of Python Tkinter and sleep
  59. Python string interception operation
  60. Python 100天速成中文教程,GitHub标星7700