Skip to content

Quantity should be an abstract base class #821

Open
@llucax

Description

@llucax

What's needed?

We should not allow to use a plan Quantity without any associated... quantity, as that's just a float.

Proposed solution

Make Quantity a ABC.

Use cases

No response

Alternatives and workarounds

No response

Additional context

The solution is probably much more complex than that, as I believe we allowed to construct "abstract quantities" to overcome complications with the type system, in particular related to Samples, that sometimes need to have a float value and sometimes a Quantity.

I've been investigating different approaches:

  • Making Sample type parameter bound to numbers.Real. This didn't work because brilliantly, isinstance(1.0, Real) is True, but using T = TypeVar("T", Real) is not good enough to the pass float as T (the types don't match). This seems to be a know bug that will not be fixed, as it seems numbers were created before type hints to solve some other problem. In any case, it will be also very hard to make Quantity be a proper Real, because we can't allow all operations (for example, if we multiply a quantity by the same type of quantity, we get quantity², not quantity, so we can't generally allow it.

  • Building our own RestrictedFloat type, or something like that, to make it compatible with float. This sort of works, but when looking at how much restricted a float needs to be to be a Quantity, there is not much left. It is basically comparison, addition and scaling.

  • Making Quantity convertible to float (implement __float__()). This seems to be the most sensible solution. By doing this the most important operations in math related to floats that we need to do in the most generic places even work without conversion, like math.isnan() and math.isinf(), so we can treat Quantitys as float directly for that and remove the isnan() and isinf() methods, being able to work with float and Quantity in a generic way. For other math, we can do v = float(quantity) and then do whatever math we need with v in a generic way. Of course we generally don't want users to convert to float, this is why we have all the as_xxx() methods, but when used generically, like in the resampler, we know we are working with the same type of quantity always, so it is safe to convert to float. Also making operations that escape the quantity (like v * v), should not make sense in resampling functions, because the new sample always need to be in the same quantity as the input samples, so that should never happen because of how math works.

Metadata

Metadata

Assignees

Labels

part:actorAffects an actor ot the actors utilities (decorator, etc.)part:coreAffects the SDK core components (data structures, etc.)part:data-pipelineAffects the data pipelinescope:breaking-changeBreaking change, users will need to update their codetype:enhancementNew feature or enhancement visitble to users

Type

No type

Projects

Status

To do

Relationships

None yet

Development

No branches or pull requests

Issue actions