Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap an object into a derived class

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 ?

like image 988
Bérenger Avatar asked Jul 09 '26 23:07

Bérenger


1 Answers

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. :)

like image 117
PM 2Ring Avatar answered Jul 11 '26 14:07

PM 2Ring



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!