TemplateMeta¶
- class lsst.utils.TemplateMeta(name, bases, attrs)¶
Bases:
type
A metaclass for abstract base classes that tie together wrapped C++ template types.
C++ template classes are most easily wrapped with a separate Python class for each template type, which results in an unnatural Python interface. TemplateMeta provides a thin layer that connects these Python classes by giving them a common base class and acting as a factory to construct them in a consistent way.
To use, simply create a new class with the name of the template class, and use
TemplateMeta
as its metaclass, and then callregister
on each of its subclasses. This registers the class with a “type key” - usually a Python representation of the C++ template types. The type key must be a hashable object - strings, type objects, and tuples of these (for C++ classes with multiple template parameters) are good choices. Alternate type keys for existing classes can be added by callingalias
, but only after a subclass already been registered with a “primary” type key. For example:.. code-block:: python
import numpy as np from ._image import ImageF, ImageD
- class Image(metaclass=TemplateMeta):
pass
Image.register(np.float32, ImageF) Image.register(np.float64, ImageD) Image.alias(“F”, ImageF) Image.alias(“D”, ImageD)
We have intentionally used
numpy
types as the primary keys for these objects in this example, with strings as secondary aliases simply because the primary key is added as adtype
attribute on the the registered classes (soImageF.dtype == numpy.float32
in the above example).This allows user code to construct objects directly using
Image
, as long as an extradtype
keyword argument is passed that matches one of the type keys:.. code-block:: python
img = Image(52, 64, dtype=np.float32)
This simply forwards additional positional and keyword arguments to the wrapped template class’s constructor.
The choice of “dtype” as the name of the template parameter is also configurable, and in fact multiple template parameters are also supported, by setting a
TEMPLATE_PARAMS
class attribute on the ABC to a tuple containing the names of the template parameters. ATEMPLATE_DEFAULTS
attribute can also be defined to a tuple of the same length containing default values for the template parameters, allowing them to be omitted in constructor calls. When the length of these attributes is more than one, the type keys passed toregister
andalias
should be tuple of the same length; when the length of these attributes is one, type keys should generally not be tuples.As an aid for those writing the Python wrappers for C++ classes,
TemplateMeta
also provides a way to add pure-Python methods and other attributes to the wrapped template classes. To add asum
method to all registered types, for example, we can just do:.. code-block:: python
class Image(metaclass=TemplateMeta):
- def sum(self):
return np.sum(self.getArray())
Image.register(np.float32, ImageF) Image.register(np.float64, ImageD)
Note
TemplateMeta
works by overriding the__instancecheck__
and__subclasscheck__
special methods, and hence does not appear in its registered subclasses’ method resolution order or__bases__
attributes. That means its attributes are not inherited by registered subclasses. Instead, attributes added to an instance ofTemplateMeta
are copied into the types registered with it. These attributes will thus replace existing attributes in those classes with the same name, and subclasses cannot delegate to base class implementations of these methods.Finally, abstract base classes that use
TemplateMeta
define a dict- like interface for accessing their registered subclasses, providing something like the C++ syntax for templates:.. code-block:: python
Image[np.float32] -> ImageF Image[“D”] -> ImageD
Both primary dtypes and aliases can be used as keys in this interface, which means types with aliases will be present multiple times in the dict. To obtain the sequence of unique subclasses, use the
__subclasses__
method.Warning
Python’s built-in
super
function does not behave properly in classes that haveTemplateMeta
as their metaclass (which should be rare, as TemplateMeta ABCs will have base classes of their own)..Methods Summary
__call__
(*args, **kwds)Call self as a function.
alias
(key, subclass)Add an alias that allows an existing subclass to be accessed with a different key.
get
(key[, default])Return the subclass associated with the given key (including aliases), or
default
if the key is not recognized.items
()Return an iterable of (key, subclass) pairs.
keys
()Return an iterable containing all keys (including aliases).
mro
(/)Return a type's method resolution order.
register
(key, subclass)Register a subclass of this ABC with the given key (a string, number, type, or other hashable).
values
()Return an iterable of registered subclasses, with duplicates corresponding to any aliases.
Methods Documentation
- __call__(*args, **kwds)¶
Call self as a function.
- alias(key, subclass)¶
Add an alias that allows an existing subclass to be accessed with a different key.
- get(key, default=None)¶
Return the subclass associated with the given key (including aliases), or
default
if the key is not recognized.
- items()¶
Return an iterable of (key, subclass) pairs.
- keys()¶
Return an iterable containing all keys (including aliases).
- mro(/)¶
Return a type’s method resolution order.
- register(key, subclass)¶
Register a subclass of this ABC with the given key (a string, number, type, or other hashable).
Register may only be called once for a given key or a given subclass.
- values()¶
Return an iterable of registered subclasses, with duplicates corresponding to any aliases.