.. _META:
Overview
########
Currently, the following meta-classes are provided:
.. #contents:: Table of Contents
:depth: 3
.. seealso::
Meta Classes
`Understanding Python metaclasses `__
Python Data Model
General :ref:`Data Model ` of Python and section about :ref:`__slots__ `.
.. _META/ExtendedType:
ExtendedType
############
The new meta-class :class:`~pyTooling.MetaClasses.ExtendedType` allows to implement :ref:`singletons `,
:ref:`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.
.. code-block:: python
class MyClass(metaclass=ExtendedType):
pass
.. _META/Slotted:
Slotted
*******
.. _META/Mixin:
Mixin
*****
.. _META/Abstract:
Abstract Method
***************
The :func:`~pyTooling.MetaClasses.abstractmethod` decorator marks a method as *abstract*. The original method gets
replaced by a method raising a :exc:`NotImplementedError`. When a class containing *abstract* methods is
instantiated, an :exc:`~pyTooling.Exceptions.AbstractClassError` is raised.
.. rubric:: Example:
.. code-block:: Python
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 :ref:`@mustoverride ` decorator.
.. _META/MustOverwrite:
MustOverwrite Method
********************
The :func:`~pyTooling.MetaClasses.mustoverride` decorator marks a method as *must override*. When a class containing
*must override* methods is instantiated, an :exc:`~pyTooling.Exceptions.MustOverrideClassError` is raised.
In contrast to :ref:`@abstractmethod `, the method can still be called from a derived class
implementing an overridden method.
.. rubric:: Example:
.. code-block:: Python
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 :ref:`@abstractmethod `
decorator.
.. _META/Singleton:
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.
.. code-block:: python
class MyClass(metaclass=ExtendedType, singleton=True):
pass
.. admonition:: Example Usage
.. code-block:: python
class Terminal(metaclass=ExtendedType, singleton=True):
def __init__(self) -> None:
pass
def WriteLine(self, message):
print(message)
.. _META/Slottedd:
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.
.. code-block:: python
class MyClass(metaclass=ExtendedType, slots=True):
pass
.. admonition:: Example Usage
.. code-block:: python
class Node(metaclass=ExtendedType, slots=True):
_parent: "Node"
def __init__(self, parent: "Node" = None) -> None:
self._parent = parent
root = Node()
node = Node(root)
.. _META/SlottedObject:
SlottedObject
=============
A class definition deriving from :class:`~pyTooling.MetaClasses.SlottedObject` will bring the slotted type behavior to
that class and all derived classes.
+----------------------------------------+----------------------------------------+----------------------------------------------------------+
| Deriving from ``SlottedObject`` | Apply ``slotted`` Decorator | Deriving from ``SlottedObject`` |
+========================================+========================================+==========================================================+
| .. code-block:: Python | .. code-block:: Python | .. code-block:: Python |
| | | |
| class MyClass(SlottedObject): | @slotted | class MyClass(metaclass=ExtendedType, slots=True): |
| pass | class MyClass(SlottedObject): | pass |
| | pass | |
+----------------------------------------+----------------------------------------+----------------------------------------------------------+
.. _META/Overloading:
Overloading
###########
.. warning:: This needs a clear definition before overloading makes sense...
This class provides a method dispatcher based on method signature's type
annotations.
.. admonition:: Example Usage
.. code-block:: python
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)