Ipywidgets взаимодействие пользователя с цепочкой функций в разных точках входа

#python #interactive #ipywidgets

#python #интерактивный #ipywidgets

Вопрос:

У меня есть цепочка шагов обработки данных в ячейке JupiterLab. Каждый шаг требует все меньше и меньше вычислений, и все они требуют пользовательского ввода. Я хотел бы выполнить вычисление только с точки, затронутой взаимодействием с пользователем, и повторно использовать результаты ранее выполненных шагов.

Вот моя попытка:

 import ipywidgets
from IPython.display import display

# This function cost a lot and I want to run it sparingly
def step1(input1):
    output1 = 10*input1
    return output1

# This function is cheap and runs frequently
# but builds on the result of the first function
def step2(output1, input2):
    output2 = output1 input2
    output2 = display(output2)
    return output2

# This function runs the whole sequence 
def process_from_step1(input1,input2):
    output1 = step1(input1)
    output2 = step2(output1, input2)
    return output1

# This function runs only the second step of the sequence 
def process_from_step2(input2):
    output1 = ie1.result
    output2 = step2(output1, input2)
    return

# User input widgets
input1_slider = ipywidgets.IntSlider()
input2_slider = ipywidgets.IntSlider()

# I'm running the full sequence at start,
# but it would be better to avoid this
process_from_step1(input1_slider.value,input2_slider.value)

ie1 = ipywidgets.interactive(process_from_step1,input1=input1_slider,input2=input2_slider)
ie2 = ipywidgets.interactive(process_from_step2 ,input2=input2_slider)

ipywidgets.VBox([ie1.children[0],ie2.children[0],ie2.children[-1]])
  

Мои вопросы:

A, В моем коде я должен использовать input2 после input1, чтобы отобразить результаты. Как я могу отобразить результаты после использования единственного входа1?

B, как я могу обобщить шаблон для более чем 2 шагов и входных данных?

Комментарии:

1. Я думаю, вам, вероятно, нужно создать свои собственные взаимодействия с observe и создать свои собственные виджеты вывода, чтобы доставить что-то подобное. Вы всегда можете кэшировать результат ваших дорогостоящих функций с помощью @lru_cache, и это может сэкономить время.

Ответ №1:

Я не уверен, что это pythonic, но, похоже, работает:

 import ipywidgets
from IPython.display import display
import time

# This function cost a lot, I want to run it sparingly
def step1(input1):
    display_result('step1 is runing')
    output = 100*input1
    return output

# This function is mid price
def step2(input1, input2):
    display_result('step2 is runing')
    output = input1 10*input2
    return output

# This function is cheap
def step3(input1, input2):
    display_result('step3 is runing')
    output = input1 input2
    return output

# Runs all steps 
def process_from_step1(input1):
    output1 = step1(input1)
    output2 = step2(output1, input2_slider.value)
    output3 = step3(output2, input3_slider.value)
    display_result(output3)
    return output1

# Reuses the results from the first step
def process_from_step2(input2): 
    output1 = step2(ie1.result, input2)
    output2 = step3(output1, input3_slider.value)
    display_result(output2)
    return output1

# Resuses the results from the first and second steps
def process_from_step3(input3):
    output1 = step3(ie2.result, input3)
    display_result(output1)
    return output1

# Displays messeages and results
def display_result(result):
    out.clear_output()
    with out:
        display(result)
    time.sleep(0.5)
    return


input1_slider = ipywidgets.IntSlider(min=0, max=9, continuous_update=False)
input2_slider = ipywidgets.IntSlider(min=0, max=9, continuous_update=False)
input3_slider = ipywidgets.IntSlider(min=0, max=9, continuous_update=False)
out = ipywidgets.Output()



ie1 = ipywidgets.interactive(process_from_step1, input1=input1_slider)
ie2 = ipywidgets.interactive(process_from_step2, input2=input2_slider)
ie3 = ipywidgets.interactive(process_from_step3, input3=input3_slider)

# runs ie1 and ie2 at first time to have ie1.result and ie2.result calculated
ie1.update()
ie2.update()

display(ipywidgets.VBox([input1_slider,input2_slider,input3_slider,out]))