Jupyter - 多个单元格中的分割类

时间:2017-07-18 08:29:50

标签: python jupyter-notebook

我想知道是否有可能将jupyter类分成不同的单元格?让我们说:

#first cell:
class foo(object):
    def __init__(self, var):
        self.var = var
#second cell
    def print_var(self):
       print(self.var)

对于更复杂的类,将它们写入一个单元格真的很烦人。 我想将每种方法放在不同的单元格中。

去年有人提出了this,但我想知道是否有内置内容,所以我不需要外部脚本/导入。

如果没有,我想知道是否有理由不提供拆分代码和文档/调试的机会。

提前致谢

4 个答案:

答案 0 :(得分:6)

在Github问题上为这个问题提供了两个解决方案"在多个单元格中定义一个Python类#1243"可在此处找到:https://github.com/jupyter/notebook/issues/1243

一个解决方案正在使用为这个特定情况开发的包中的一个魔术函数,称为jdc - 或Jupyter动态类。有关如何安装以及如何使用的文档可以在https://alexhagen.github.io/jdc/

的包网址上找到

第二个解决方案Doug Blank提供,它只适用于常规Python,而不需要采取任何额外的魔法,如下所示:

单元格1:

class MyClass():
    def method1(self):
        print("method1")

Cell 2:

class MyClass(MyClass):
    def method2(self):
        print("method2")

小组3:

instance = MyClass()
instance.method1()
instance.method2()

我自己在Jupyter Notebook和VS Code中测试了第二个解决方案,它在两个环境中都运行良好,除了我在VS Code中得到一个pylint错误[pylint] E0102:class already defined line 5,这是预期的但仍然运行良好。而且,无论如何,VS Code并不是目标环境。

答案 1 :(得分:4)

我不觉得整件事情是一个问题或一个好主意......但也许以下内容对您有用:

# First cell
class Foo(object):
    pass
# Other cell
def __init__(self, var):
    self.var = var

Foo.__init__ = __init__
# Yet another cell
def print_var(self):
   print(self.var)
Foo.print_var = print_var

我不希望它非常强大,但......它应该适用于常规课程。

编辑:我认为有几种情况可能会破坏。我不确定这是否会抵制代码检查,因为该方法存在并且远远超过#34;来自全班。但是你使用的是笔记本电脑,所以代码检查应该不是问题(?),尽管在调试时请记住这一点。

另一个可能的问题可能与使用元类有关。如果您尝试使用元类(或从某些使用元类的类派生)可能会破坏它,因为元类通常希望能够知道类的所有方法,并通过动态地向类添加方法,我们正在弯曲关于班级创作流程的规则。

没有元类或一些非常奇怪的"用例,方法应该是安全的。

对于"简单"课程,这是一种非常有效的方法。但是......它并不是一个预期的功能,所以(ab)使用它可能会带来一些我可能没有的其他问题

答案 2 :(得分:0)

没有办法拆分单个班级, 但是,您可以将方法动态添加到它的实例

CELL#1

import types
class A:
    def __init__(self, var):
        self.var = var

a = A()

在另一个细胞中:

CELL#2

def print_var(self):
    print (self.var)
a.print_var = types.MethodType( print_var, a )

现在,这应该有效:

CELL#3

a.print_var()

答案 3 :(得分:0)

Medhat Omr 的 answer 提供了一些不错的选择;我发现我认为有人可能会觉得有用的另一个方法是使用装饰器函数为类动态分配方法。例如,我们可以创建一个像下面这样的高阶函数,它接受一些任意函数,以字符串形式获取其名称,并将其分配为类方法。

def classMethod(func):
    setattr(MyClass, func.__name__, func)
    return func

然后我们可以在应该绑定到类的每个方法上方使用装饰器的语法糖;

@classMethod
def get_numpy(self):
    return np.array(self.data)

这样,每个方法都可以存储在不同的 Jupyter notebook 单元中,并且每次运行单元时都会使用新函数更新类。

我还应该注意,由于这会将方法初始化为全局范围内的函数,因此最好在它们前面加上下划线或字母以避免名称冲突(然后将 func.__name__ 替换为 {{1 }} 或者您想省略的每个名称开头的字符。该方法仍然具有“错位”名称,因为它是同一个对象,因此如果您需要以编程方式访问其他地方的方法名称,请注意这一点你的程序。