3

Suppose I have a class A coming from a third-party library (FYI it is numpy.matrix). I want to expand its public interface with a wrapper class B.

class B(A):
    def myMethod(self,arg):
        return 'spam'

And also, I want to create B objects from A object. Since B will not hold any more attribute, I just really want to return the A object, with the B behavior:

class B(A):
    def __new__(cls,a): # type(a)==A
        return a.castTo(B) # pseudo-code

Is there a way to do it in python ?

Similarily, is there a way to cast B objects to A objects ?

3
  • Related: stackoverflow.com/questions/25394550/… Commented Oct 5, 2014 at 3:51
  • 1
    @NickT: Thank you. It seems to be sooo complicated. Isn't the language supporting this kind of basic OOP stuff ? In C++ it would be a short one-liner. Same in ruby (AFAIK). Or Python does not work this way ? I am confused... Commented Oct 5, 2014 at 4:10
  • Seems like you should be able to use a decorator: thecodeship.com/patterns/guide-to-python-function-decorators Commented Oct 5, 2014 at 4:55

1 Answer 1

2

Your class B's __new__ needs to call A's __new__. Here's a brief demo using the built-in list class.

class mylist(list):
    def __new__(cls, obj=None):
        return list.__new__(cls, obj)

    def mymethod(self, msg):
        print msg, id(self)


def main():
    a = mylist('abc')
    print a, id(a)
    a.mymethod('hello')


if __name__ == '__main__':
    main()

If you just want to add a simple function to an instance of an existing class, you can do this sort of thing.

class A(object):
    pass

def silly(arg=None):
    print 'This is silly', arg

b = A()
b.my = silly
b.my()

Note that b.my it just a function, not a method, so it does not get passed self when you call it. But you can pass it "by hand" by doing b.my(b)


Edit

As an alternative to writing list.__new__(cls, obj), you can call the super() function:

def __new__(cls, obj=None):
    return super(mylist, cls).__new__(cls, obj)

But in most cases using the base class name is clearer and shorter. I guess there might be a reason to prefer super(), but I'm not enough of an expert on this stuff to say. :)

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, the first part is the answer I expected. I wasn't able to find anything on the internet. I used _new to return [], not list.__new__(cls, obj), so I ended up with a base class object.
I learned about that syntax from Guido, in the docs, but it's not something I've used often.
Note that the super() calling syntax has been simplified in Python 3. docs.python.org/3/library/functions.html?super#super

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.