Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3664430
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 19, 20262026-05-19T01:38:44+00:00 2026-05-19T01:38:44+00:00

Is it possible to chain metaclasses? I have class Model which uses __metaclass__=ModelBase to

  • 0

Is it possible to chain metaclasses?

I have class Model which uses __metaclass__=ModelBase to process its namespace dict. I’m going to inherit from it and “bind” another metaclass so it won’t shade the original one.

First approach is to subclass class MyModelBase(ModelBase):

MyModel(Model):
    __metaclass__ = MyModelBase # inherits from `ModelBase`

But is it possible just to chain them like mixins, without explicit subclassing? Something like

class MyModel(Model):
    __metaclass__ = (MyMixin, super(Model).__metaclass__)

… or even better: create a MixIn that will use __metaclass__ from the direct parent of the class that uses it:

class MyModel(Model):
    __metaclass__ = MyMetaMixin, # Automagically uses `Model.__metaclass__`

The reason: For more flexibility in extending existing apps, I want to create a global mechanism for hooking into the process of Model, Form, … definitions in Django so it can be changed at runtime.

A common mechanism would be much better than implementing multiple metaclasses with callback mixins.


With your help I finally managed to come up to a solution: metaclass MetaProxy.

The idea is: create a metaclass that invokes a callback to modify the namespace of the class being created, then, with the help of __new__, mutate into a metaclass of one of the parents

#!/usr/bin/env python
#-*- coding: utf-8 -*-

# Magical metaclass
class MetaProxy(type):
    """ Decorate the class being created & preserve __metaclass__ of the parent

        It executes two callbacks: before & after creation of a class, 
        that allows you to decorate them.

        Between two callbacks, it tries to locate any `__metaclass__` 
        in the parents (sorted in MRO). 
        If found — with the help of `__new__` method it
        mutates to the found base metaclass. 
        If not found — it just instantiates the given class.
        """

    @classmethod
    def pre_new(cls, name, bases, attrs):
        """ Decorate a class before creation """
        return (name, bases, attrs)

    @classmethod
    def post_new(cls, newclass):
        """ Decorate a class after creation """
        return newclass

    @classmethod
    def _mrobases(cls, bases):
        """ Expand tuple of base-classes ``bases`` in MRO """
        mrobases = []
        for base in bases:
            if base is not None: # We don't like `None` :)
                mrobases.extend(base.mro())
        return mrobases

    @classmethod
    def _find_parent_metaclass(cls, mrobases):
        """ Find any __metaclass__ callable in ``mrobases`` """
        for base in mrobases:
            if hasattr(base, '__metaclass__'):
                metacls = base.__metaclass__
                if metacls and not issubclass(metacls, cls): # don't call self again
                    return metacls#(name, bases, attrs)
        # Not found: use `type`
        return lambda name,bases,attrs: type.__new__(type, name, bases, attrs)

    def __new__(cls, name, bases, attrs):
        mrobases = cls._mrobases(bases)
        name, bases, attrs = cls.pre_new(name, bases, attrs) # Decorate, pre-creation
        newclass = cls._find_parent_metaclass(mrobases)(name, bases, attrs)
        return cls.post_new(newclass) # Decorate, post-creation



# Testing
if __name__ == '__main__':
    # Original classes. We won't touch them
    class ModelMeta(type):
        def __new__(cls, name, bases, attrs):
            attrs['parentmeta'] = name
            return super(ModelMeta, cls).__new__(cls, name, bases, attrs)

    class Model(object):
        __metaclass__ = ModelMeta
        # Try to subclass me but don't forget about `ModelMeta`

    # Decorator metaclass
    class MyMeta(MetaProxy):
        """ Decorate a class

            Being a subclass of `MetaProxyDecorator`,
                it will call base metaclasses after decorating
            """
        @classmethod
        def pre_new(cls, name, bases, attrs):
            """ Set `washere` to classname """
            attrs['washere'] = name
            return super(MyMeta, cls).pre_new(name, bases, attrs)

        @classmethod
        def post_new(cls, newclass):
            """ Append '!' to `.washere` """
            newclass.washere += '!'
            return super(MyMeta, cls).post_new(newclass)

    # Here goes the inheritance...
    class MyModel(Model):
        __metaclass__ = MyMeta
        a=1
    class MyNewModel(MyModel):
        __metaclass__ = MyMeta # Still have to declare it: __metaclass__ do not inherit
        a=2
    class MyNewNewModel(MyNewModel):
        # Will use the original ModelMeta
        a=3

    class A(object):
        __metaclass__ = MyMeta # No __metaclass__ in parents: just instantiate
        a=4
    class B(A): 
        pass # MyMeta is not called until specified explicitly



    # Make sure we did everything right
    assert MyModel.a == 1
    assert MyNewModel.a == 2
    assert MyNewNewModel.a == 3
    assert A.a == 4

    # Make sure callback() worked
    assert hasattr(MyModel, 'washere')
    assert hasattr(MyNewModel, 'washere')
    assert hasattr(MyNewNewModel, 'washere') # inherited
    assert hasattr(A, 'washere')

    assert MyModel.washere == 'MyModel!'
    assert MyNewModel.washere == 'MyNewModel!'
    assert MyNewNewModel.washere == 'MyNewModel!' # inherited, so unchanged
    assert A.washere == 'A!'
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-19T01:38:44+00:00Added an answer on May 19, 2026 at 1:38 am

    I don’t think you can chain them like that, and I don’t know how that would work either.

    But you can make new metaclasses during runtime and use them. But that’s a horrid hack. 🙂

    zope.interface does something similar, it has an advisor metaclass, that will just do some things to the class after construction. If there was a metclass already, one of the things it will do it set that previous metaclass as the metaclass once it’s finished.

    (However, avoid doing these kinds of things unless you have to, or think it’s fun.)

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Does someone knows if it's possible to dynamically create a call chain and invoke
Possible Duplicate: NAnt or MSBuild, which one to choose and when? What is the
Possible Duplicate: How does the Google Did you mean? Algorithm work? Suppose you have
I want to make a trait which add some property to a class and
I'm researching the possible use of the jquery plugin chain.js over other templating systems
is it possible in rails 2.3.X to start a new chain of commands after
I would like to know if its possible, by using JSF, to make somethings
Possible Duplicate: Why not use tables for layout in HTML? Under what conditions should
Possible Duplicate: How do I calculate someone's age in C#? Maybe this could be
Possible Duplicate: .NET - What’s the best way to implement a catch all exceptions

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.