2

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?

5
  • 1
    How is this question related to metaclasses? Commented Sep 13, 2012 at 22:30
  • fooNew is created using the type metaclass? I'm new to metaclasses and probably wrong Commented Sep 13, 2012 at 22:31
  • 1
    Yeah, type is the standard built-in metaclass. If people say "using metaclasses", they usually refer to defining custom metaclasses. All you do here is to use a rather inconvenient way to dynamically create a class. Commented Sep 13, 2012 at 22:34
  • Thanks Sven. What would be the better way to create this class? Commented Sep 13, 2012 at 22:37
  • I updated my answer with one way. Commented Sep 13, 2012 at 22:38

2 Answers 2

5

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
Sign up to request clarification or add additional context in comments.

Comments

3

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.

2 Comments

newbar_factory is missing return newbar.
I tought a little about the matter, and agree this is the way to go.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.