Help creating new module which inherits existing class from another module.

Steven D'Aprano steve at pearwood.info
Wed Feb 19 02:52:08 EST 2014


On Tue, 18 Feb 2014 14:34:51 -0600, Jonno wrote:

> There is an existing module I want to use which has a class we'll call
> *Existing Class*.
> 
> I want to create a python module which allows me to create *new_objects*
> with the following properties:
> 
>    - The new_objects have all the attributes of the Existing_Class
>    (simply create a class that inherits from Existing_Class) 

That part is easy:

from some_module import ExistingClass

class NewClass(ExistingClass):
    pass

newobject = NewClass()


>    - I then
>    want to create a nested structure under the new_objects something
>    like:
> 
> new_object.foo
> 
> new_object.foo.bar
> 
> new_object.foo.bar.baz
> 
> Where foo, bar, baz have the following properties:
> 
>    - All have *docstrings*
>    - All are available for *tab completion* tools upon new_object
>    creation. 

Well, that depends on the tab completion tools you are using.


>    - Some of which will have *new methods* which act in the following
>    way:
>    - new_object.foo.bar()
> 
>    calls
>    - new_object.existing_method("foo.bar", *args)


Seems awfully complicated, and I don't understand what you would do with 
these strange things, but okay.

Start by ignoring the "existing class" and concentrated on these foo, 
foo.bar, foo.bar.baz things. It isn't clear to me what they are, but I 
think that you want foo to be an object which is callable, as well as 
having an attribute bar (which itself is callable, etc.). The way to do 
that is with a class:

class FooClass:
    def __init__(self, parent):
        self.parent = parent

    def __call__(self):
        return self.parent.existing_method("something")

Add your foo, bar and baz methods as needed, and we'll look for a way to 
calculate "something" on the fly later.


Now remember your NewClass definition above? What we'd like to do is this:

class NewClass(ExistingClass):
    foo = FooClass(self)

but of course you can't, because self doesn't exist until the class is 
instantiated! So what we need if for foo to be a descriptor. I don't 
quite remember the descriptor syntax, so this may be wrong, but I think 
you want something like this:

# This is probably wrong.
class FooDescriptor(object):
    def __get__(self, cls, obj):
        return FooClass(obj)

and then in NewClass you put in:

    foo = FooDescriptor()


The idea is that when you have a NewClass instance, calling 
"newobject.foo" will automatically call the descriptor's __getmethod__, 
passing it the class and instance. That descriptor will create and 
populate the FooClass instance, which does the real work.

Descriptors are how methods, classmethods, staticmethods and properties 
work, so they are a fundamental, powerful way of implementing things like 
this.

-- 
Steven



More information about the Python-list mailing list