使用观察函数调用在 select 框中显示子类别列表的函数仅在第一次工作

calling a function which shows sub category list in a select box using observe function is working only first time

I have simple df have main category and its sub items. I made two select boxes to select main category and it automatically shows belonged items at the other select box using 'observe' But it works only at the first time category selection and after I selected another category it didn't show sub items in an another select box.

If i put 'observe' inside the 'def' the function is worked as I wanted. But this approach is troublesome if I have many other 'def' executing on observe on change. I am also looking for the way to make this code simple without using global. And also welcome any ideas to make this code simpler and lighter.

import pandas as pd
import ipywidgets as wg
from ipywidgets import *
from IPython.display import display, clear_output
df_list=[{'Category':'fruit','name':['banana','apple','mango']},\
         {'Category':'animal','name':['lion','monkey','tiger','cat','dog']},\
         {'Category':'body','name':['eyes','hands','ears','arms']},\
         {'Category':'office','name':['table','computer','printer']}]
df=pd.DataFrame(df_list)

Category_box=wg.Select(options=list(df.Category),continuous_update=False,layout=Layout(width='30%'))
name_box=wg.Select(options=list(df[df['Category']==Category_box.value].name)[0],continuous_update=False,\
                   layout=Layout(width='30%'))
hbox=wg.HBox(children=[Category_box,name_box])
display(hbox)

def select_on_change(change):
    if change['name'] == 'value':
        global Category_box
        global name_box
        global hbox
        Category_box=wg.Select(options=list(df.Category),continuous_update=False,layout=Layout(width='30%'),value=Category_box.value)
        name_box=wg.Select(options=list(df[df['Category']==Category_box.value].name)[0],continuous_update=False,\
                   layout=Layout(width='30%'))
        hbox=wg.HBox(children=[Category_box,name_box])
        clear_output()
        display(hbox)
    #Category_box.observe(select_on_change)


Category_box.observe(select_on_change)

首先,感谢您提供完整清晰的示例。

解决方案是不要在您正在观察的函数中创建新的小部件。而只是更新 name_box 小部件的 .options。这样,不需要全局变量。

import pandas as pd
import ipywidgets as wg
from ipywidgets import *
from IPython.display import display, clear_output
df_list=[{'Category':'fruit','name':['banana','apple','mango']},\
         {'Category':'animal','name':['lion','monkey','tiger','cat','dog']},\
         {'Category':'body','name':['eyes','hands','ears','arms']},\
         {'Category':'office','name':['table','computer','printer']}]
df=pd.DataFrame(df_list)

Category_box=wg.Select(options=list(df.Category),continuous_update=False,layout=Layout(width='30%'))
name_box=wg.Select(options=list(df[df['Category']==Category_box.value].name)[0],continuous_update=False,\
                   layout=Layout(width='30%'))
hbox=wg.HBox(children=[Category_box,name_box])
display(hbox)

def select_on_change(change):
    if change['name'] == 'value':
        name_box.options = list(df[df['Category']==Category_box.value].name)[0]


Category_box.observe(select_on_change)