<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python+Dash快速web應(yīng)用開發(fā):回調(diào)交互篇(上)

          共 6825字,需瀏覽 14分鐘

           ·

          2021-01-22 20:28


          添加微信號"CNFeffery"加入技術(shù)交流群
          ?

          本文示例代碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes

          ?

          1 簡介

          這是我的系列教程「Python+Dash快速web應(yīng)用開發(fā)」的第三期,在前兩期的教程中,我們圍繞什么是Dash,以及如何配合方便好用的第三方拓展dash-bootstrap-components來為我們的Dash應(yīng)用設(shè)計(jì)布局展開了非常詳細(xì)的介紹。

          Dash最吸引我的地方在于其高度封裝了react.js,使得我們無需編寫js語句,純Python編程就可以實(shí)現(xiàn)瀏覽器前端與后端計(jì)算之間常規(guī)的異步通信,從而創(chuàng)造出功能強(qiáng)大的交互式web應(yīng)用。

          圖1

          從今天的文章開始,我就將開始帶大家走進(jìn)Dash的核心內(nèi)容——「回調(diào)」。

          2 Dash中的基礎(chǔ)回調(diào)

          2.1 最基礎(chǔ)的回調(diào)

          Dash中的「回調(diào)」callback)是以裝飾器的形式,配合自編回調(diào)函數(shù),實(shí)現(xiàn)前后端異步通信交互,這句話可能不太好理解,我們從一個(gè)簡單的例子出發(fā)來認(rèn)識Dash中的「回調(diào)」

          ?

          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)
          ????????????????????]
          ????????????????)
          ????????????]
          ????????)
          ????]
          )


          #?對應(yīng)app實(shí)例的回調(diào)函數(shù)裝飾器
          @app.callback(
          ????Output('output-value',?'children'),
          ????Input('input-value',?'value')
          )
          def?input_to_output(input_value):
          ????'''
          ????簡單的回調(diào)函數(shù)
          ????'''

          ????return?input_value


          if?__name__?==?'__main__':
          ????app.run_server()

          先來看看app1的交互效果:

          圖2

          下面我們來分解上面的代碼,梳理一下要構(gòu)造一個(gè)具有實(shí)際交互功能的Dash應(yīng)用需要做什么:

          • 「確定輸入與輸出部件」

          一個(gè)可交互的系統(tǒng)一定是有「輸入」「輸出」的,我們開頭導(dǎo)入的InputOutput對象,他們分別扮演著「輸入者」「輸出者」兩種角色,其各自的第一個(gè)參數(shù)component_id用于聯(lián)動(dòng)前端部分定義的部件。

          我們在前面定義前端部件時(shí),為dbc.Input對應(yīng)的輸入框設(shè)置了id='input-value',為dbc.Label對應(yīng)的文字輸出設(shè)置了id='output-value',讓它們作為第一個(gè)參數(shù)可以被Input()Output()唯一識別出來。

          • 「確定輸入與輸出內(nèi)容」

          在確定了「輸入者」「輸出者」之后,更重要的是為告訴Dash需要監(jiān)聽什么輸入,響應(yīng)什么輸出,這就要用到第二個(gè)參數(shù)component_property。

          它與對應(yīng)的前端部件有關(guān),譬如我們的dbc.Input()輸入框,其被輸入的內(nèi)容都存在value屬性中,而children屬性是dbc.Label以及絕大多數(shù)html部件的第一個(gè)參數(shù),這樣我們就確定了輸入輸出內(nèi)容。

          • 「裝飾回調(diào)函數(shù)」

          app.callback()裝飾器按照規(guī)定的先Output()Input()的順序傳入相應(yīng)對象,而既然是裝飾器,自然需要配合自定義回調(diào)函數(shù)使用。

          我們的input_to_output()就是對應(yīng)的回調(diào)函數(shù),其參數(shù)與裝飾器中的Input()對應(yīng),而函數(shù)內(nèi)部則用來定義計(jì)算處理過程。

          最后return的對象則對應(yīng)Output()。

          #?對應(yīng)app實(shí)例的回調(diào)函數(shù)裝飾器
          @app.callback(
          ????Output('output-value',?'children'),
          ????Input('input-value',?'value')
          )
          def?input_to_output(input_value):
          ????'''
          ????簡單的回調(diào)函數(shù)
          ????'''

          ????return?input_value

          通過上面這樣的結(jié)構(gòu),我們得以純Python“寥寥數(shù)語”實(shí)現(xiàn)了交互功能,賦予我們編寫任意功能Dash應(yīng)用的能力。

          2.2 同時(shí)設(shè)置多個(gè)Input()與Output()

          在上一小節(jié)中我們介紹的是最基本的「單輸入 -> 單輸出」回調(diào)模式,很多時(shí)候我們需要更復(fù)雜的回調(diào)模式,譬如下面的例子:

          ?

          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?'請輸入合法參數(shù)!'


          if?__name__?==?'__main__':
          ????app.run_server()
          圖3

          這里我們的Input()對象不止一個(gè),在Output()對象之后依次傳入(也可以把所有Input()對象包在一個(gè)列表中傳入),其順序?qū)?yīng)后面回調(diào)函數(shù)的參數(shù)順序,從而實(shí)現(xiàn)了多個(gè)輸入值的一一對應(yīng)。

          同樣的,Output()也可以有多個(gè):

          ?

          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

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

          2.3 利用State()實(shí)現(xiàn)惰性交互

          很多情況下,如果我們的回調(diào)函數(shù)計(jì)算過程時(shí)間開銷較大,那么像前面介紹的僅靠Input()Output()實(shí)現(xiàn)的前后端通信會(huì)很頻繁,因?yàn)楸O(jiān)聽到的所有輸入部件對應(yīng)屬性值只要略一改變,就會(huì)觸發(fā)回調(diào)。

          為了解決這類問題,Dash中設(shè)計(jì)了State()對象,我們可以利用State()替換Input()來綁定對應(yīng)的輸入值,再將一些需要主動(dòng)觸發(fā)的譬如dbc.Button()按鈕部件的屬性n_clicks,作為Input()對象進(jìn)行綁定。

          讓我們通過下面的例子更好的理解它的作用:

          ?

          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('小寫轉(zhuǎn)大寫',
          ???????????????????????????????????????????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()的順序傳入各個(gè)對象后,我們的Button()部件的n_clicks參數(shù)記錄了對應(yīng)的按鈕被點(diǎn)擊了多少次,初始化我們設(shè)置其為0,之后每次等我們輸入完單詞,主動(dòng)去點(diǎn)擊按鈕從而增加其被點(diǎn)擊次數(shù)記錄時(shí),回調(diào)函數(shù)才會(huì)被觸發(fā),這樣就方便了我們的很多復(fù)雜應(yīng)用場景~


          以上就是本期的全部內(nèi)容,歡迎在評論區(qū)與我進(jìn)行討論~

          加入知識星球【我們談?wù)摂?shù)據(jù)科學(xué)】

          300+小伙伴一起學(xué)習(xí)!






          · 推薦閱讀?·

          這個(gè)Pandas函數(shù)可以自動(dòng)爬取Web圖表

          Python+Dash快速web應(yīng)用開發(fā)——頁面布局篇

          Python+Dash快速web應(yīng)用開發(fā)——基礎(chǔ)概念篇


          瀏覽 74
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩黄色免費在线视頻 | 天天射天天色综合网 | 暴操美女网站 | 五月丁香五月 | 操逼网站在线视频 |