Overview

Currently, the following meta-classes are provided:

See also

Meta Classes

Understanding Python metaclasses

Python Data Model

General Data Model of Python and section about __slots__.

ExtendedType

The new meta-class ExtendedType allows to implement singletons, slotted types and combinations thereof.

Since Python 3, meta-classes are applied in a class definition by adding a named parameter called metaclass to the list of derived classes (positional parameters). Further named parameters might be given to pass parameters to that new meta-class.

class MyClass(metaclass=ExtendedType):
  pass

Slotted

Mixin

Abstract Method

The abstractmethod() decorator marks a method as abstract. The original method gets replaced by a method raising a NotImplementedError. When a class containing abstract methods is instantiated, an AbstractClassError is raised.

Example:

class A(metaclass=ExtendedType):
  @abstractmethod
  def method(self) -> int:
    """Methods documentation."""

class B(A):
  @InheritDocString(A)
  def method(self) -> int:
    return 2

Hint

If the abstract method should contain code that should be called from an overriding method in a derived class, use the @mustoverride decorator.

MustOverwrite Method

The mustoverride() decorator marks a method as must override. When a class containing must override methods is instantiated, an MustOverrideClassError is raised.

In contrast to @abstractmethod, the method can still be called from a derived class implementing an overridden method.

Example:

class A(metaclass=ExtendedType):
  @mustoverride
  def method(self) -> int:
    """Methods documentation."""
    return 2

class B(A):
  @InheritDocString(A)
  def method(self) -> int:
    result = super().method()
    return result + 1

Hint

If the method contain no code and throw an exception when called, use the @abstractmethod decorator.

Singleton

A class defined with enabled singleton behavior implements the singleton design pattern, which allows only a single instance of that class to exist. If another instance is going to be created, a previously cached instance of that class will be returned.

class MyClass(metaclass=ExtendedType, singleton=True):
  pass

Example Usage

class Terminal(metaclass=ExtendedType, singleton=True):
  def __init__(self) -> None:
    pass

  def WriteLine(self, message):
    print(message)

Slotted Type

A class defined with enabled slots behavior stores instance fields in slots. The meta-class, translates all type-annotated fields in a class definition into slots. Slots allow a more efficient field storage and access compared to dynamically stored and accessed fields hosted by __dict__. This improves the memory footprint as well as the field access performance of all class instances. This behavior is automatically inherited to all derived classes.

class MyClass(metaclass=ExtendedType, slots=True):
  pass

Example Usage

class Node(metaclass=ExtendedType, slots=True):
  _parent: "Node"

  def __init__(self, parent: "Node" = None) -> None:
    self._parent = parent

root = Node()
node = Node(root)

SlottedObject

A class definition deriving from SlottedObject will bring the slotted type behavior to that class and all derived classes.

Deriving from SlottedObject

Apply slotted Decorator

Deriving from SlottedObject

class MyClass(SlottedObject):
  pass
@slotted
class MyClass(SlottedObject):
  pass
class MyClass(metaclass=ExtendedType, slots=True):
  pass

Overloading

Warning

This needs a clear definition before overloading makes sense…

This class provides a method dispatcher based on method signature’s type annotations.

Example Usage

class A(metaclass=Overloading):
  value = None

  def __init__(self, value : int = 0) -> None:
    self.value = value

  def __init__(self, value : str) -> None:
    self.value = int(value)

a = A()
print(a.value)

b = A(3)
print(b.value)

c = A("42")
print(c.value)