从实例方法定义的Jupyter魔术

时间:2018-08-25 21:28:16

标签: python methods jupyter-notebook python-decorators

我正在编写一个类,该类在进程完成后向用户发送松弛消息。我认为提供Jupyter魔术很有用,这样在执行单元格时可以通知用户。

该类已经提供了一个装饰器,所以我想我只是将一个单元执行包装在一个装饰函数中。

from IPython.core.magic import register_cell_magic
from IPython import get_ipython

import functools

class MyClass(object):

    def decorate(self, f):
        @functools.wraps(f)
        def wrapped(*args, **kwargs):
            r = f(*args, **kwargs)
            print('Send a message here!')
            return r
        return wrapped

    @register_cell_magic
    def magic(self, line, cell):
        ip = get_ipython()
        @self.decorate
        def f():
            return ip.run_cell(cell)
        return f()

所以我会做:

obj = MyClass()

# ----- NEW CELL
%%obj.magic
'''do some stuff'''

但是我明白了

>> UsageError: Cell magic `%%obj.magic` not found.

我发现魔术是以其名称注册的(上面是magic),因此%%magic可以工作。但是然后,所有参数都搞砸了,因为混合中没有self

我希望魔术成为实例方法,以便配置(可以使用__init__中的设置)。有什么办法吗?

这里有两个我不想实施的骇人解决方案,除非我真的需要:

  1. 使用该实例作为参数注册一个常规函数。我不想将那行代码添加到笔记本中,我想使用实例方法
  2. 注册一个即时构造实例的常规函数​​。

1 个答案:

答案 0 :(得分:1)

这是我能想到的最好的方法,它在我不想做的事情清单上排名第一。

from IPython.core.magic import register_cell_magic
from IPython import get_ipython

import functools

class MyClass(object):

    def decorate(self, f):
        @functools.wraps(f)
        def wrapped(*args, **kwargs):
            r = f(*args, **kwargs)
            print('Send a message here!')
            return r
        return wrapped


    def register_magic(self):
        @register_cell_magic
        def magic(line, cell):
            ip = get_ipython()
            @self.decorate
            def f():
                return ip.run_cell(cell)
            return f()

然后

obj = MyClass()
obj.register_magic()

# ------
%%magic
...