2

I want to automatically run a class method defined in a base class on any derived class during the creation of the class. For instance:

class Base(object):
  @classmethod
  def runme():
    print "I am being run"

  def __metclass__(cls,parents,attributes):
    clsObj = type(cls,parents,attributes)
    clsObj.runme()
    return clsObj


class Derived(Base):
  pass:

What happens here is that when Base is created, ''runme()'' will fire. But nothing happens when Derived is created.

The question is: How can I make ''runme()'' also fire when creating Derived.

This is what I have thought so far: If I explicitly set Derived's metaclass to Base's, it will work. But I don't want that to happen. I basically want Derived to use the Base's metaclass without me having to explicitly set it so.

4

4 回答 4

2

See this answer. Basically, when calling type(cls,parents,attributes), you are creating a class without passing in the information about what that class's metaclass is. Thus, the class that is returned doesn't have the metaclass you want it to; instead it has metaclass type. (Ironically, by defining __metaclass__ to do as it does, you are explicitly causing your class to not have that metaclass.) Instead of directly calling type, you need to call type.__new__(meta, cls, parents, attrs), where meta is the metaclass.

However, you can't achieve this when you define __metaclass__ inline. From inside your __metaclass__ method, you have no way to refer to that method, because it's a method of a class that hasn't been defined yet. You want to do something like

def __metaclass__(cls, bases, attrs):
    type.__new__(metaclassGoesHere, cls, bases, attrs)

. . . but there's nothing you can put in for metaclassGoesHere to make it do the right thing, because what you're trying to refer to is the method inside which you're trying to refer to it.

So just define your metaclass externally.

于 2012-06-21T03:40:19.393 回答
0

rename your runme() to __init__(self) and DO NOT override the __init__() method, and it will get called every time you make an instance of Derived

class Base(object):
    def __init__(self):
        print "I am being run"

class Derived(Base):
    pass

dummy_instance = Derived()

Copy and paste that, it will print I am being run.

于 2012-06-21T03:11:59.463 回答
0

Try This,

class MyMetaclass(type): 

    def __new__(cls, name, bases, dct):

        runme()

        return super(MyMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
于 2012-06-21T04:19:01.550 回答
0

If you want to do something when the class is created you have to do it in the __init__ method of __metaclass__.

class foo(object):
    @classmethod
    def method(cls):
        print 'I am being run by', cls.__name__

    class __metaclass__(type):
        def __init__(self, *args, **kwargs):
            type.__init__(self, *args, **kwargs)
            self.method()

class bar(foo): pass

Which prints:

I am being run by foo
I am being run by bar
于 2013-11-15T19:50:19.000 回答