Search code examples
pythonmetaclass

Can I avoid the ```metaclass=``` when I define an inherited class?


I would like to have a custom metaclass that looks like the definition of a TypedDict.

When one declares a new TypedDict we write something like this:

from typing import TypedDict

class MyClass(TypedDict, total=False):
  pass

However, when I declare a metaclass, it looks like this:

class MetaSerial(type):
  def __new__(pls, name, bases, act, exclude: list[str] = [], custom: list[str] = []):
    dct["_exclude"] = exclude
    dct["_custom"] = custom
    return super().__new__(cls, name, bases, dct)

class Serial(metaclass=MetaSerial, exclude=["value"], custom=["terminals"]):
  pass

So, the million dollar question is: is there a way for me to get rid of the annoying metaclass= and use something like:

class Serial(MetaSerial, exclude=["value"], custom=["terminals"]):
  pass

Solution

  • Avoid metaclasses where possible (every metaclass you define is a potential conflict with another metaclass). All you need here is a base class with an appropriate __init_subclass__ method.

    class SerialBase:
        def __init_subclass__(cls, exclude: list[str] = None, custom: list[str] = None, **kwargs):
            super().__init_subclass__(**kwargs)
            if exclude is None:
                exclude = []
    
            if custom is None:
                custom = []
    
            cls._exclude = exclude
            cls._custom = custom
    
    class Serial(SerialBase, exclude=["value"], custom=["terminals"]):
        pass