【问题标题】:How to have an argument possible values dependent on another argument with IPython Widgets?如何让一个参数的可能值依赖于 IPython Widgets 的另一个参数?
【发布时间】:2016-10-26 00:10:47
【问题描述】:

假设我在 Python 中有这个简单的函数:

def f(gender, name):
    if gender == 'male':
        return ranking_male(name)
    else:
        return ranking_female(name)

其中gender 属于['male', 'female']name 属于['Adam', 'John', 'Max', 'Frodo'](如果gendermale)或['Mary', 'Sarah', 'Arwen'](否则)。

我希望将interactipywidgets 应用到这个函数f。通常一个人会这样做

from ipywidgets import interact
interact(f, gender = ('male', 'female'), name = ('Adam', 'John', 'Max', 'Frodo'))

问题是name 的允许值现在取决于为gender 选择的值。

我试图在文档中找到它,但找不到。我认为唯一可能重要的是 这用于设置特征更改的动态通知。

    Parameters
    ----------
    handler : callable
        A callable that is called when a trait changes. Its
        signature should be ``handler(change)``, where ``change```is a
        dictionary. The change dictionary at least holds a 'type' key.
        * ``type``: the type of notification.
        Other keys may be passed depending on the value of 'type'. In the
        case where type is 'change', we also have the following keys:
        * ``owner`` : the HasTraits instance
        * ``old`` : the old value of the modified trait attribute
        * ``new`` : the new value of the modified trait attribute
        * ``name`` : the name of the modified trait attribute.
    names : list, str, All
        If names is All, the handler will apply to all traits.  If a list
        of str, handler will apply to all names in the list.  If a
        str, the handler will apply just to that name.
    type : str, All (default: 'change')
        The type of notification to filter by. If equal to All, then all
        notifications are passed to the observe handler.

但我不知道该怎么做,也不知道文档字符串在说什么。非常感谢任何帮助!

【问题讨论】:

    标签: widget ipython jupyter jupyter-notebook ipywidgets


    【解决方案1】:

    我使用嵌套小部件来解决这个问题。它会起作用,但它很难看,部分原因是它似乎不是ipywidgets (see discussion) 中的常见用例。

    给定你的函数f(gender, name),你可以定义一个中间包装器:

    def f_intermediate_wrapper(gender):
        if gender=="male":
            possible_names = ['Adam', 'John', 'Max', 'Frodo']
        else:
            possible_names = ['Mary', 'Sarah', 'Arwen']
    
        try:
            f_intermediate_wrapper.name_widget.widget.close()
        except AttributeError:
            pass
    
        f_intermediate_wrapper.name_widget = interact(f,
                                                      gender=widgets.fixed(gender),
                                                      name = possible_names)   
    

    第一部分根据需要设置给定性别的可能名称选项。

    第二部分关闭您之前评估的name_widget(如果存在)。否则,每次更改性别时,都会留下旧的姓名列表,即性别错误 (see example)。

    第三部分创建该性别的可能名称的名称小部件,并将其存储在足够静态的地方。 (否则,当您更改性别时,旧名称小部件将超出范围,您将无法关闭它。)

    现在您可以创建您的性别和姓名小部件:

    gender_and_name_widget = interact(f_intermediate_wrapper,
                                      gender = ["male", "female"])
    

    您可以使用f(gender, name) 访问结果

    gender_and_name_widget.name_widget.widget.result
    

    【讨论】:

      【解决方案2】:

      例如,您有汽车的brandmodel,而model 取决于brand

      d = {'Volkswagen' : ['Tiguan', 'Passat', 'Polo', 'Touareg', 'Jetta'], 'Chevrolet' : ['TAHOE', 'CAMARO'] }
      
      brand_widget = Dropdown( options=list(d.keys()),
                               value='Volkswagen',
                               description='Brand:',
                               style=style
                             )
      model_widget = Dropdown( options=d['Volkswagen'],
                               value=None,
                               description='Model:',
                               style=style
                             )
      
      def on_update_brand_widget(*args):
          model_widget.options = d[brand_widget.value]
      
      brand_widget.observe(on_update_brand_widget, 'value')
      

      【讨论】:

      猜你喜欢
      • 2011-03-06
      • 2021-07-05
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多