Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a benefit to defining a class inside another class in Python?

Tags:

python

oop

You might want to do this when the "inner" class is a one-off, which will never be used outside the definition of the outer class. For example to use a metaclass, it's sometimes handy to do

class Foo(object):
    class __metaclass__(type):
        .... 

instead of defining a metaclass separately, if you're only using it once.

The only other time I've used nested classes like that, I used the outer class only as a namespace to group a bunch of closely related classes together:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

Then from another module, you can import Group and refer to these as Group.cls1, Group.cls2 etc. However one might argue that you can accomplish exactly the same (perhaps in a less confusing way) by using a module.


I don't know Python, but your question seems very general. Ignore me if it's specific to Python.

Class nesting is all about scope. If you think that one class will only make sense in the context of another one, then the former is probably a good candidate to become a nested class.

It is a common pattern make helper classes as private, nested classes.


There is another usage for nested class, when one wants to construct inherited classes whose enhanced functionalities are encapsulated in a specific nested class.

See this example:

class foo:

  class bar:
    ...  # functionalities of a specific sub-feature of foo

  def __init__(self):
    self.a = self.bar()
    ...

  ...  # other features of foo


class foo2(foo):

  class bar(foo.bar):
    ... # enhanced functionalities for this specific feature

  def __init__(self):
    foo.__init__(self)

Note that in the constructor of foo, the line self.a = self.bar() will construct a foo.bar when the object being constructed is actually a foo object, and a foo2.bar object when the object being constructed is actually a foo2 object.

If the class bar was defined outside of class foo instead, as well as its inherited version (which would be called bar2 for example), then defining the new class foo2 would be much more painful, because the constuctor of foo2 would need to have its first line replaced by self.a = bar2(), which implies re-writing the whole constructor.


You could be using a class as class generator. Like (in some off the cuff code :)

class gen(object):
    class base_1(object): pass
    ...
    class base_n(object): pass

    def __init__(self, ...):
        ...
    def mk_cls(self, ..., type):
        '''makes a class based on the type passed in, the current state of
           the class, and the other inputs to the method'''

I feel like when you need this functionality it will be very clear to you. If you don't need to be doing something similar than it probably isn't a good use case.