在 Jupyter 的多个单元格中拆分 class 函数?

Splitting class functions across multiple cells in Jupyter?

给定以下代码:

class DTC:
    def __init__(self):
        self.__root = None

    def unique(self,Y):
        d = {}
        for i in Y:
            if i not in d:
                d[i]=1
            else:
                d[i]+=1
        return d

    def ent(self,Y):
        freq = self.__count_unique(Y)
        ent_ = 0
        total = len(Y)
        for i in freq:
            p = freq[i]/total
            entropy_ += (-p)*math.log2(p)
        return ent_

如果放在 Jupyter Notebook 的单个单元格中,上面的内容将 运行。但是,如果我希望 class 代码像这样分成多个单元格,我该如何使它工作:

单元格 1

class DTC:
    def __init__(self):
        self.__root = None

单元格 2

    def unique(self,Y):
        d = {}
        for i in Y:
            if i not in d:
                d[i]=1
            else:
                d[i]+=1
        return d

单元格 3

    def ent(self,Y):
        freq = self.__unique(Y)
        ent_ = 0
        total = len(Y)
        for i in freq:
            p = freq[i]/total
            ent_ += (-p)*math.log2(p)
        return ent_

在 Jupyter Notebooks 中有两种方法可以将 class 定义拆分到多个单元格

方法一

以天真的方式进行(利用继承和覆盖):

单元格 1

class DTC:
    def __init__(self):
        self.__root = None

Cell-2

class DTC(DTC):
    def unique(self,Y):
        d = {}
        for i in Y:
            if i not in d:
                d[i]=1
            else:
                d[i]+=1
        return d

单元格 3

class DTC(DTC):
    def ent(self,Y):
        freq = self.__count_unique(Y)
        ent_ = 0
        total = len(Y)
        for i in freq:
            p = freq[i]/total
            entropy_ += (-p)*math.log2(p)
        return ent_

需要注意的是,这实际上在内部创建了一个 classes 的层次结构:

import inspect
inspect.getmro(DTC)
# outputs: (__main__.DTC, __main__.DTC, __main__.DTC, object)

如果您不打算拉伸太多单元格,您可以使用此方法。

方法二

使用包jdc; more details/docs for jdc

单元格 1

import jdc        # jupyter dynamic classes

class DTC:
    def __init__(self):
        self.__root = None

单元格 2

%%add_to DTC
def unique(self,Y):
    d = {}
    for i in Y:
        if i not in d:
            d[i]=1
        else:
            d[i]+=1
    return d

单元格 3

%%add_to DTC
def ent(self,Y):
    freq = self.__count_unique(Y)
    ent_ = 0
    total = len(Y)
    for i in freq:
        p = freq[i]/total
        entropy_ += (-p)*math.log2(p)
    return ent_

这次没有形成层次结构:

import inspect
inspect.getmro(DTC)
#output: (__main__.DTC, object)

一个python-only解决方案:

class OutsourceMethods:
    @classmethod
    def method(cls, f):
        setattr(cls, f.__name__, f)
        

用作:

class A(SuperA, OutsourceMethods):
    def __init__(self):
        self.x = 10


@A.method
def bar(self, y):
    print(self.x, y)

a = A()

a.bar(20)

> 10 20

b = A()
b.x = 3
b.bar() 

> 3 20

它不等于 100%,但到目前为止我还没有注意到有什么不同。