6

After reading the excellent SO post, I tried crafting a module level metaclass:

def metaclass(future_class_name, future_class_parents, future_class_attrs):
    print "module.__metaclass__"
    future_class_attrs["bar"]="bar"
    return type(future_class_name, future_class_parents, future_class_attrs)

__metaclass__=metaclass


class Foo(object):

    def __init__(self):
        print 'Foo.__init__'

f=Foo()

This doesn't work (i.e. "module.metaclass" doesn't get printed) unless I remove the object base class of Foo. How come?

NOTE: I am using Python 2.6.1.

2 Answers 2

3

Inheriting from object automatically brings the type metaclass along with it. This overrides your module level __metaclass__ specification.

If the metaclass is specified at the class level, then object won't override it:

def metaclass(future_class_name, future_class_parents, future_class_attrs):
    print "module.__metaclass__"
    future_class_attrs["bar"]="bar"
    return type(future_class_name, future_class_parents, future_class_attrs)

class Foo(object):
    __metaclass__ = metaclass

    def __init__(self):
        print 'Foo.__init__'

f=Foo()

See http://docs.python.org/reference/datamodel.html?highlight=metaclass#customizing-class-creation

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

1 Comment

The specification says no such thing. What it does say is that if there is a baseclass, the metaclass of the baseclass will be used, regardless of whether or not the baseclass specifies a metaclass.
2

The specification specifies the order in which Python will look for a metaclass:

The appropriate metaclass is determined by the following precedence rules:

  • If dict['__metaclass__'] exists, it is used.
  • Otherwise, if there is at least one base class, its metaclass is used (this looks for a __class__ attribute first and if not found, uses its type).
  • Otherwise, if a global variable named __metaclass__ exists, it is used.
  • Otherwise, the old-style, classic metaclass (types.ClassType) is used.

You will see from the above that having a base class at all (whatever the base class is, even if it does not ultimately inherit from object) pre-empts the module-level __metaclass__.

Comments

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.