Return value from function where ipython widgets a

2019-02-27 15:01发布

I'm trying to "widgetize" my IPython notebooks and am running into trouble with events and returning values from a function. This is the workflow I'm thinking is the best way to go:

  • using widgets to get the input values for an arbitrary function
  • call the function on event trigger
  • return value from function

I first tried using the "interact" method to call the function, but that seemed difficult to associate events and return values. From reading other interactive examples, making a class seemed like the way to go. I don't write classes very often; so hopefully my error is something simple there.

The following makes two widgets, and when the user presses "Enter" should call a function and store its return value in the class for future use.

In reality, it fires off the function two times before I enter any text and throws 'unicode object is not callable' when I change value.



    import ipywidgets as widgets
    from IPython.display import display

    def any_function_returning_value(word1,word2):
        new_word = 'Combining words is easy: %s %s'%(word1,word2)
        print new_word
        return new_word

    class learn_classes_and_widgets():
        def __init__(self, param1 = 'a word', param2 = 'another word'):
            self.p1_text = widgets.Text(description = 'Word #1',value = param1)
            self.p2_text = widgets.Text(description = 'Word #2',value = param2)
            self.p1_text.on_submit(self.handle_submit())
            self.p2_text.on_submit(self.handle_submit())
            display(self.p1_text, self.p2_text)

        def handle_submit(self):
            print "Submitting"
            self.w = any_function_returning_value(self.p1_text.value,self.p2_text.value)
            return self.w

    f = learn_classes_and_widgets(param1 = 'try this word')
    #f.w should contain the combined words when this is all working

1条回答
Viruses.
2楼-- · 2019-02-27 15:12

Answered by Oliver Ruebel via email. Here are his fixes to my problems.

Assignment to on_submit is wrong

When you call the on.submit function you need to hand it the function you want to call. In you code this looks like this.

self.p1_text.on_submit(self.handle_submit())
self.p2_text.on_submit(self.handle_submit())

However, what you are code does is it calls self.handle_submit (because you included the "()" brackets after the function) and then assigns the return value of that function to your on submit handle. This explains the behavior you are seeing. I.e., the function is called twice in your init() and then when the event happens it trys to act on the string that was returned by the function. The fix for this is simple, just remove the "()", i.e.:

self.p1_text.on_submit(self.handle_submit)
self.p2_text.on_submit(self.handle_submit)

The handle_submit function signature is wrong

The handle submit function must accept the text object of the widget as input. I.e., you will get self.p1_text or self.p2_text as input, depending on which widget calls it. I.e., your function should look like this:

def handle_submit(self, text):
...

With the above changes, everything should work as expected. However, if you want to implement different behaviors for the different widgets you should use different handle functions for the different widgets and place any shared behavior into some other function that is called by your handle function.

import ipywidgets as widgets
from IPython.display import display

def any_function_returning_value(word1,word2):
    new_word = 'Combining words is easy: %s %s'%(word1,word2)
    print new_word
    return new_word

class learn_classes_and_widgets():
    def __init__(self, param1 = 'a word', param2 = 'another word'):
        self.p1_text = widgets.Text(description = 'Word #1',value = param1)
        self.p2_text = widgets.Text(description = 'Word #2',value = param2)
        self.p1_text.on_submit(self.handle_submit)
        self.p2_text.on_submit(self.handle_submit)
        display(self.p1_text, self.p2_text)

    def handle_submit(self, text):
        print "Submitting"
        print "Text " + str(text.value)
        self.w = any_function_returning_value(self.p1_text.value,self.p2_text.value)
        return self.w

f = learn_classes_and_widgets(param1 = 'try this word')
查看更多
登录 后发表回答