Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jupyter - Split Classes in multiple Cells

I wonder if there is a possibility to split jupyter classes into different cells? Lets say:


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

#second cell
    def print_var(self):
       print(self.var)

For more complex classes its really annoying to write them into one cell. I would like to put each method in a different cell.

Someone made this this last year but i wonder if there is something build in so i dont need external scripts/imports.

And if not, i would like to know if there is a reason to not give the opportunity to split your code and document / debug it way easier.

Thanks in advance

like image 762
Florian H Avatar asked Jul 18 '17 08:07

Florian H


People also ask

How do you split cells in Jupyter Notebook?

Enter command mode ( Esc ), use Shift + s to toggle the current cell to either a split cell or full width.

What is %% capture in Jupyter?

What does %% capture do in Jupyter? Capturing Output With %%capture IPython has a cell magic, %%capture , which captures the stdout/stderr of a cell. With this magic you can discard these streams or store them in a variable. By default, %%capture discards these streams. This is a simple way to suppress unwanted output.

How do you collapse multiple cells in Jupyter Notebook?

If you structure your Jupyter Notebook with headings, you can collapse the information and cells within that same heading section with the down arrow to the left of the heading.

How do you tab multiple lines in a Jupyter Notebook?

For me, selecting multiple lines and doing tab (for indenting) and shift+tab (for removing indenting) works.


2 Answers

Two solutions were provided to this problem on Github issue "Define a Python class across multiple cells #1243" which can be found here: https://github.com/jupyter/notebook/issues/1243

One solution is using a magic function from a package developed for this specific case called jdc - or Jupyter dynamic classes. The documentation on how to install it and how to use can be found on package url at https://alexhagen.github.io/jdc/

The second solution was provided by Doug Blank and which just work in regular Python, without resorting to any extra magic as follows:

Cell 1:

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

Cell 2:

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

Cell 3:

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

I tested the second solution myself in both Jupyter Notebook and VS Code, and it worked fine in both environments, except that I got a pylint error [pylint] E0102:class already defined line 5 in VS Code, which is kind of expected but still runs fine. Moreover, VS Code was not meant to be the target environment anyway.

like image 108
Medhat Omr Avatar answered Oct 12 '22 11:10

Medhat Omr


I don't feel like that whole stuff to be a issue or a good idea... But maybe the following will work for you:


# 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

I don't expect it to be extremely robust, but... it should work for regular classes.

EDIT: I believe that there are a couple of situations where this may break. I am not sure if that will resist code inspection, given that the method lives "far" from the class. But you are using a notebook, so code inspection should not be an issue (?), although keep that in mind if debugging.

Another possible issue can be related to use of metaclasses. If you try to use metaclasses (or derive from some class which uses a metaclass) that may broke it, because metaclasses typically expect to be able to know all the methods of the class, and by dynamically adding methods to a class, we are bending the rules on the flow of class creation.

Without metaclasses or some "quite-strange" use cases, the approach should be safe-ish.

For "simple" classes, it is a perfectly valid approach. But... it is not exactly an expected feature, so (ab)using it may give some additional problems which I may not

like image 40
MariusSiuram Avatar answered Oct 12 '22 11:10

MariusSiuram