It is worth considering how much "array" interface the Quaternion class should have. Examples of array interface can include:
the ability to multiply/divide/dx scalar quaternions by multi-quaternions (not allowed right now)
the ability to iterate over quaternions in a multi-quaternion.
broadcasting to multiply/divide/dx arbitrarily-sized multi-quaternions. The most common use case is N x 1, e.g. you have a single initial quaternion and you want to find the delta for a vector of Quats.
It is worth considering how much "array" interface the Quaternion class should have. Examples of array interface can include:
Astropy has a nice mixin class that is used for exactly the purpose of implementing much of the numpy shape-related API on non-numpy classes: https://github.com/astropy/astropy/blob/7bd65c6d88fa6052ea8a0d7b75761076e255c0f4/astropy/utils/misc.py#L893