获取 class 中的 ipywidget 按钮以通过自身访问 class 参数?

Get ipywidget button within a class to access class parameters through self?

我正在写一个 class,我想包含多个可以在 Jupyter notebook 中显示的小部件。这些小部件应该调用更新 class 参数的 class 方法。我连接到 ipywidget 事件的函数需要访问 class 实例,我通过自我思考,但我无法弄清楚如何使这种通信工作。

这是一个最小的例子:

import numpy as np
import ipywidgets as widgets

class Test(object):
    def __init__(self):
        self.val = np.random.rand()
        display(self._random_button)

    _random_button = widgets.Button(
        description='randomize self.val'
    )

    def update_random(self):
        self.val = np.random.rand()
        print(self.val)

    def button_pressed(self):
        self.update_random()

    _random_button.on_click(button_pressed)

我看到 button_pressed() 函数如何将 Button 实例视为 self,给出 "AttributeError: 'Button' object has no attribute 'update_random'"。

有没有一种方法可以让我通过属于 class 的按钮访问 class 测试的方法,或者有没有更好的方法来构建此代码以简化这些组件之间的通信?

  1. 按钮小部件和 on_click 应该在 init 方法中创建(或初始化)。
  2. on_click 方法生成一个参数发送给函数,但在这种情况下不需要它,所以我只是在 button_pressed 函数中放置了一个 *args。
  3. 不需要显示调用。
  4. 在class中调用函数时,必须使用self.functionName。这包括 on_clickobserve
  5. 中的函数调用
  6. 在这种情况下,您不需要在 init 函数中生成随机数。

此处 class 中有几个 Jupyter 小部件示例:https://github.com/bloomberg/bqplot/tree/master/examples/Applications

import numpy as np
import ipywidgets as widgets

class Test(object):
    def __init__(self):
        self.random_button = widgets.Button(
            description='randomize self.val')
        self.random_button.on_click(self.button_pressed)

    def update_random(self):
        self.val = np.random.rand()
        print(self.val)

    def button_pressed(self,*args):
        self.update_random()

buttonObject = Test()
# display(buttonObject.random_button)  # display works but is not required if on the last line in Jupyter cell.
buttonObject.random_button  # Widget to be dispalyed - must last last line in cell

使用 JupyterLab 时,如果您希望输出显示在笔记本单元格中,而不是笔记本日志中,则需要对@DougR 的出色回答进行细微调整:

import numpy as np
import ipywidgets as widgets

# create an output widget
rand_num_output = widgets.Output()

class Test(object):
    def __init__(self):
        self.random_button = widgets.Button(
            description='randomize self.val')
        self.random_button.on_click(self.button_pressed)

    def update_random(self):
        # clear the output on every click of randomize self.val
        rand_num_output.clear_output()
        
        # execute function so it gets captured in output widget view
        with rand_num_output:
            self.val = np.random.rand()
            print(self.val)

    def button_pressed(self,*args):
        self.update_random()

buttonObject = Test()
# display(buttonObject.random_button)  # display works but is not required if on the last line in Jupyter cell.
widgets.HBox([buttonObject.random_button, rand_num_output])  # Widget to be dispalyed - must last last line in cell, add output widget