2016-06-23 2 views
3

Предположит, у меня есть эта простая функция в Python:Как аргумент возможных значений зависит от другого аргумента с IPython Widgets?

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'] (в противном случае).

Я хочу применить interact от ipywidgets к этой функции 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. 

Но я не знаю, как это сделать или не интерпретировать то, о чем говорит строка doc. Любая помощь высоко ценится!

ответ

1

к примеру у вас есть brand и model автомобиля и 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') 
+0

очень интересно! Благодаря! можете ли вы объяснить, что делает эта линия? 'brand_widget.observe (on_update_brand_widget, 'value')' – gota

+0

Регистрация обратного вызова: http://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Events.html#Traitlet-events – mrgloom

0

Я использовал вложенные виджеты для решения этой проблемы. Он будет работать, но он уродлив, частично потому, что он не выглядит обычным делом в 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