Question

I'm trying to use metaclasses to implement the following functionality:

class foo( object ):

    def __init__( self ):
        self.val = 'foo'

    def bar( self ):
        print 'hello world'
        print self.val

f = foo()
f.bar() #prints 'hello world' followed by foo

def newbar( self ):
    super( **?**, self).bar()
    print 'another world!'

fooNew = type('fooNew', (foo,), {'bar':newbar})
n = fooNew()
n.bar() # should print everything in f.bar() followed by 'another world!'

I understand I can use monkey patching to implement my own function newbar. However there is a subtle difference, I want the new bar function to first run the base class bar function and only then run any additional functionality.

How can I do this? or how could I do this better?

Était-ce utile?

La solution

You can change the definition of newbar to return a function instead:

def newbar_factory(cls):
    def newbar(self):
        super(cls, self).bar()
        # Alternately, as Sven points out you could do
        # cls.bar(self)
        print "another world!"

    return newbar

# Use
fooNew = type('fooNew', (foo,), {'bar':newbar_factory(foo)})

There is probably a better way to accomplish the kind of thing you are trying to do - but this should do the trick.

Autres conseils

Using super() to call base class methods has advantages in certain multiple inheritance situations, but disadvantages in most other cases (which is, in 95 % of use cases). So simply don't use super() here, but rather call the base class method directly.

I would go yet another way (provided I'm sure I really want to dynamically create a class). You can define the whole class inside a function and return it:

def class_factory():
    class NewFoo(foo):
        def bar(self):
            foo.bar()
            print 'another world!'
    return NewFoo
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top