在Dash中使用作为实例变量的Dash对象作为Python装饰器回调-失败

在Dash中使用作为实例变量的Dash对象作为Python装饰器回调-失败,python,callback,python-decorators,plotly-dash,Python,Callback,Python Decorators,Plotly Dash,我正在更新一些代码以使用Dash和plotly。绘图的主代码在类中定义。我用Dash控件替换了一些Bokeh小部件,最后得到了一个如下所示的回调: class MakeStuff: def __init__(self, ..., **optional): ... self.app = dash.Dash(...) ... @self.app.callback( dash.dependencies.Output('indic

我正在更新一些代码以使用Dash和plotly。绘图的主代码在类中定义。我用Dash控件替换了一些Bokeh小部件,最后得到了一个如下所示的回调:

class MakeStuff:
    def __init__(self, ..., **optional):
        ...
        self.app = dash.Dash(...)
        ...

    @self.app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
        [dash.dependencies.Input('start-time-slider', 'value'),
         dash.dependencies.Input('graph-width-slider', 'value')]
        )
    def update_graphs(self,range_start,graph_width):
        print(...)
我下面是一些例子。我能够运行示例,包括回调。在我的代码中,没有decorator,代码运行时不会出错,生成了我期望的图形和控件。(当然,代码是不完整的,但没有错误。)当我包含decorator时,我得到以下错误:

NameError:未定义名称“self”

首先,我只是模仿代码示例:

class MakeStuff:
    def __init__(self, ..., **optional):
        ...
        app = dash.Dash(...)
        ...

    @app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
    [dash.dependencies.Input('start-time-slider', 'value'),
     dash.dependencies.Input('graph-width-slider', 'value')]
    )
    def update_graphs(self,range_start,graph_width):
        print(...)
当然,变量“app”仅在init函数的范围内已知,因此这不起作用也就不足为奇了,并给出了类似的错误:

NameError:未定义名称“app”


有没有一种简单的方法可以让这个装饰器在保持代码在类定义中的同时工作?我猜装饰程序正在进行一些预处理,但我对它的理解还不够透彻,无法想出解决方案。

您可以调用回调函数,而不是作为装饰程序,如中所示。这应该在
\uuuu init\uuu
函数中起作用:

class MakeStuff:
    def __init__(self, ..., **optional):
        ...
        self.app = dash.Dash(...)
        app.callback(dash.dependencies.Output('indicator-graphic', 'figure'),
            [dash.dependencies.Input('start-time-slider', 'value'),
             dash.dependencies.Input('graph-width-slider', 'value')])(self.update_graphs)
        ...

    def update_graphs(self,range_start,graph_width):
        print(...)
我以前从未在类实例中尝试过它,但没有理由认为它不起作用。

ned2提供了一个解决方案,他使用以下结构在类定义中设置装饰器

class BaseBlock:
def __init__(self, app=None):
    self.app = app

    if self.app is not None and hasattr(self, 'callbacks'):
        self.callbacks(self.app)

class MyBlock(BaseBlock):
    layout = html.Div('layout for this "block".')

    def callbacks(self, app):

        @app.callback(Output('foo', 'figure'), [Input('bar')])
        def do_things(bar):
            return SOME_DATA

        @app.callback(Output('baz', 'figure'), [Input('boop')])
        def do_things(boop):
            return OTHER_DATA

# creating a new MyBlock will register all callbacks
block = MyBlock(app=app)

# now insert this component into the app's layout 
app.layout['slot'] = block.layout