Steps towards making the objects effectively immutable (true immutability in Python is unachievable and probably undesirable):
Units and quantities are now hashable
Equality logic is better
Units and quantities now use __slots__, meaning only a select few private variables can be changed, and those are protected as properties already
This last change seems to have a mild memory hit, which is worth recording here for the future...
Usually, the main advantage of __slots__ is a decrease in memory use. Weirdly, though, the various objects are actually bigger when they have __slots__ instead of __dict__:
Sizes in memory (via `sys.getsizeof()`) with/without slots:
With Without
int 28 B
decimal.Decimal 104 B
BaseUnit 72 B 56 B
CompoundUnit 80 B 56 B
DerivedUnit 80 B 56 B
PrefixedUnit 96 B 56 B
Quantity 56 B 56 B
Quant w/ Uncert 56 B 56 B
Prefix 56 B 56 B
Quant w/ Unit from unit_reg 56 B 56 B
Quant w/ CompoundUnit 136 B 112 B
Total all units ~17.7 kB ~11.4 kB
(~117 + 87 prefixed)
Note that the above are from Python 3.11; in Python 3.12 it seems that all the objects are only 48 B without slots (but the same with).
When using a pre-defined unit, a quantity is thus basically the same size with or without.
However, since the unit of a quantity is often a compound unit created on creation of the quantity, this makes the effective size of many quantities 21% larger.
At the current size of the units selection, the overall footprint with all units imported is ~50% larger, but since this is so small in absolute terms this is likely nowhere near as important as the memory footprint of quantities.
Given the size of Decimal instances in comparison, the slight memory increase seems unimportant, so for now I will merge the use of slots.
Performance of unit and quantity creation, property access, and arithmetic is ever so slightly improved, with 1-2% savings when using slots.
Steps towards making the objects effectively immutable (true immutability in Python is unachievable and probably undesirable):
__slots__
, meaning only a select few private variables can be changed, and those are protected as properties alreadyThis last change seems to have a mild memory hit, which is worth recording here for the future...
Usually, the main advantage of
__slots__
is a decrease in memory use. Weirdly, though, the various objects are actually bigger when they have__slots__
instead of__dict__
:Note that the above are from Python 3.11; in Python 3.12 it seems that all the objects are only 48 B without slots (but the same with).
When using a pre-defined unit, a quantity is thus basically the same size with or without.
However, since the unit of a quantity is often a compound unit created on creation of the quantity, this makes the effective size of many quantities 21% larger.
At the current size of the units selection, the overall footprint with all units imported is ~50% larger, but since this is so small in absolute terms this is likely nowhere near as important as the memory footprint of quantities.
Given the size of
Decimal
instances in comparison, the slight memory increase seems unimportant, so for now I will merge the use of slots.Performance of unit and quantity creation, property access, and arithmetic is ever so slightly improved, with 1-2% savings when using slots.