我在IPython中使用的小部件允许用户重复搜索短语,并在另一个小部件(选择小部件)中查看结果(不同的标题),然后选择其中一个结果。
简而言之:
search_text = widgets.Text(description = 'Search')
search_result = widgets.Select(description = 'Select table')
def search_action(sender):
phrase = search_text.value
df = search(phrase) # A function that returns the results in a pandas df
titles = df['title'].tolist()
search_result.options = titles
search_text.on_submit(search_action)
这以前工作得很好,但在更新到最新版本的ipywidgets(从4.0.1升级为5.1.3)后,它看起来像
search_selection.options = titles
产生以下错误(一个或两个,不同):
TraitError: Invalid selection
TypeError: 'list' object is not callable
它仍然可以工作,因为小部件会根据其他小部件的搜索结果进行更新,但会出现错误。
根据另一个小部件的结果,在一个小程序中设置选项的正确方法是什么?
(编辑:添加了更详细的错误消息)
我一小时前遇到了这个问题。我用这里的最小示例拼凑了一个解决方案:动态更改IPython笔记本小部件和Spyre中的下拉列表,因为我自己的要求是具有动态链接列表。我相信您将能够使用此解决方案来调整您的需求。
关键是预生成所有下拉列表/选择。由于某种原因,w.options = l
只设置w._options_labels
,而不设置w.options
。随后对w
的选定值的验证将严重失败。
import ipywidgets as widgets
from IPython.display import display
geo={'USA':['CHI','NYC'],'Russia':['MOW','LED']}
geoWs = {key: widgets.Select(options=geo[key]) for key in geo}
def get_current_state():
return {'country': i.children[0].value,
'city': i.children[1].value}
def print_city(**func_kwargs):
print('func_kwargs', func_kwargs)
print('i.kwargs', i.kwargs)
print('get_current_state', get_current_state())
def select_country(country):
new_i = widgets.interactive(print_city, country=countryW, city=geoWs[country['new']])
i.children = new_i.children
countryW = widgets.Select(options=list(geo.keys()))
init = countryW.value
cityW = geoWs[init]
countryW.observe(select_country, 'value')
i = widgets.interactive(print_city, country=countryW, city=cityW)
display(i)
最后请注意,获取小部件的最新状态并非易事。这些是
- 通过
get_current_state
直接从儿童的价值观中获得。这是值得信赖的 - 从交互式实例,通过
i.kwargs
- 从提供的参数到
print_city
后两者有时可能已经过时,因为各种原因,我不想进一步了解。
希望这能有所帮助。
您可以在分配给options
:期间保留的通知
with search_result.hold_trait_notifications():
search_result.options = titles
因此:
search_text = widgets.Text(description = 'Search')
search_result = widgets.Select(description = 'Select table')
def search_action(sender):
phrase = search_text.value
df = search(phrase) # A function that returns the results in a pandas df
titles = df['title'].tolist()
with search_result.hold_trait_notifications():
search_result.options = titles
参见下文中hmelberg的解释
错误的根源是小部件还有一个value属性,该值可能不在新的选项列表中。因此,小部件的值可能会在短时间内"孤立",从而产生错误。
我遇到了一个类似的问题,并解决了它在内核中注册对特征变化的回调
caption = widgets.Label(value='The values of range1 and range2 are synchronized')
slider = widgets.IntSlider(min=-5, max=5, value=1, description='Slider')
def handle_slider_change(change):
caption.value = 'The slider value is ' + (
'negative' if change.new < 0 else 'nonnegative'
)
slider.observe(handle_slider_change, names='value')
display(caption, slider)
我想这个解决方案在2016年还不可用,或者我的问题并不像想象的那样相似。
错误的根源是小部件还有一个value属性,并且该值可能不在新的选项列表中。因此,小部件值可能会在短时间内"孤立",并产生错误。
解决方案是在将小部件值分配给小部件之前将其分配给选项列表(如果需要,在之后删除值/选项),或者如Dan所写:使用createa hold_trait-notifications()
丹的方法是最好的。以上只是解释了问题的原因。