#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]))