2. Quantity¶
Unit-safe computations with quantities.
2.1. Usage¶
2.1.1. Defining a quantity class¶
A basic type of quantity is declared just by sub-classing
Quantity
:
>>> class Length(Quantity):
... pass
...
In addition to the new quantity class the meta-class of Quantity
creates a corresponding class for the units automatically. It can be
referenced via the quantity class:
>>> Length.Unit
<class 'quantity.quantity.LengthUnit'>
But, as long as there is no unit defined for that class, you can not create any instance for the new quantity class:
>>> l = Length(1)
ValueError: A unit must be given.
If there is a reference unit, the simplest way to define it is giving a name
and a symbol for it as class variables. The meta-class of Quantity
will then create a unit automatically:
>>> class Length(Quantity):
... refUnitName = 'Metre'
... refUnitSymbol = 'm'
...
>>> Length.refUnit
Length.Unit('m')
Now, this unit can be given to create a quantity:
>>> METRE = Length.refUnit
>>> print(Length(15, METRE))
15 m
If no unit is given, the reference unit is used:
>>> print(Length(15))
15 m
Other units can be derived from the reference unit (or another unit), giving a definition by multiplying a scaling factor with that unit:
>>> MILLIMETRE = Length.Unit('mm', 'Millimetre', Decimal('0.001') * METRE)
>>> MILLIMETRE
Length.Unit('mm')
>>> KILOMETRE = Length.Unit('km', 'Kilometre', 1000 * METRE)
>>> KILOMETRE
Length.Unit('km')
>>> CENTIMETRE = Length.Unit('cm', 'Centimetre', 10 * MILLIMETRE)
>>> CENTIMETRE
Length.Unit('cm')
Using one unit as a reference and defining all other units by giving
a scaling factor is only possible if the units have the same scale. Otherwise,
units have to be instantiated via the coresponding Unit
sub-class
without giving a definition:
>>> class Temperature(Quantity):
... pass
...
>>> CELSIUS = Temperature.Unit('°C', 'Degree Celsius')
>>> FAHRENHEIT = Temperature.Unit('°F', 'Degree Fahrenheit')
>>> KELVIN = Temperature.Unit('K', 'Kelvin')
Derived types of quantities are declared by giving a definition based on more basic types of quantities:
>>> class Volume(Quantity):
... defineAs = Length ** 3
... refUnitName = 'Cubic Metre'
...
>>> class Duration(Quantity):
... refUnitName = 'Second'
... refUnitSymbol = 's'
...
>>> class Velocity(Quantity):
... defineAs = Length / Duration
... refUnitName = 'Metre per Second'
...
If no symbol for the reference unit is given with the class declaration, a symbol is generated from the definition, as long as all types of quantities in that definition have a reference unit.
>>> print(Volume.refUnit.symbol)
m³
>>> print(Velocity.refUnit.symbol)
m/s
Other units have to be defined explicitly. For derived quantities, the
function generateUnits()
can be used to create all units from the
cross-product of all units of the quantity classes the class is derived from.
In order to define a quantized quantity, the smallest possible fraction
(in terms of the reference unit) can be given as class variable quantum. The
class method Quantity.getQuantum()
can then be used to retrieve the
smallest fraction for any unit:
>>> class DataVolume(Quantity):
... refUnitName = 'Byte'
... refUnitSymbol = 'B'
... quantum = Fraction(1, 8)
...
>>> BYTE = DataVolume.refUnit
>>> KILOBYTE = DataVolume.Unit('kB', 'Kilobyte', Decimal(1000) * BYTE)
>>> DataVolume.getQuantum(KILOBYTE)
Decimal('0.000125')
2.1.2. Instantiating quantities¶
The simplest way to create an instance of a Quantity
subclass is to
call the class giving an amount and a unit. If the unit is omitted, the
quantity’s reference unit is used (if one is defined):
>>> Length(15, MILLIMETRE)
Length(Decimal(15), Length.Unit(u'mm'))
>>> Length(15)
Length(Decimal(15))
Alternatively, the two-args infix operator ‘^’ can be used to combine an amount and a unit:
>>> 17.5 ^ KILOMETRE
Length(Decimal('17.5'), Length.Unit(u'km'))
Also, it’s possible to create a Quantity
instance from a string
representation:
>>> Length('17.5 km')
Length(Decimal('17.5'), Length.Unit(u'km'))
If a unit is given in addition, the resulting quantity is converted accordingly:
>>> Length('17 m', KILOMETRE)
Length(Decimal('0.017'), Length.Unit(u'km'))
Instead of calling a subclass, the class Quantity
can be used as a
factory function …:
>>> Quantity(15, MILLIMETRE)
Length(Decimal(15), Length.Unit(u'mm'))
>>> Quantity('17.5 km')
Length(Decimal('17.5'), Length.Unit(u'km'))
… as long as a unit is given:
>>> Quantity(17.5)
ValueError: A unit must be given.
If the Quantity
subclass defines a quantum, the amount of each
instance is automatically rounded to this quantum:
>>> DataVolume('1/7', KILOBYTE)
DataVolume(Decimal('0.142875'), DataVolume.Unit('kB'))
2.1.3. Converting between units¶
A quantity can be converted to a quantity using a different unit by calling
the method Quantity.convert()
:
>>> l5cm = Length(Decimal(5), CENTIMETRE)
>>> l5cm.convert(MILLIMETRE)
Length(Decimal('50'), Length.Unit('mm'))
>>> l5cm.convert(KILOMETRE)
Length(Decimal('0.00005'), Length.Unit('km'))
To get just the amount of a quantity in another unit, that unit can be called with the quantity as parameter:
>>> MILLIMETRE(l5cm)
Decimal('50')
>>> KILOMETRE(l5cm)
Decimal('0.00005')
These kinds of conversion are automatically enabled for types of quantities with reference units. For other types of quantities there is no default way of converting between units.
>>> t27c = Temperature(Decimal(27), CELSIUS)
>>> t27c.convert(FAHRENHEIT)
quantity.quantity.IncompatibleUnitsError: Can't convert 'Degree Celsius' to 'Degree Fahrenheit'
2.1.3.1. Converters¶
For types of quantities that do not have a reference unit, one or more callables can be registered as converters:
>>> def fahrenheit2celsius(qty, toUnit):
... if qty.unit is FAHRENHEIT and toUnit is CELSIUS:
... return (qty.amount - 32) / Decimal('1.8')
... return None
...
>>> def celsius2fahrenheit(qty, toUnit):
... if qty.unit is CELSIUS and toUnit is FAHRENHEIT:
... return qty.amount * Decimal('1.8') + 32
... return None
...
>>> Temperature.Unit.registerConverter(celsius2fahrenheit)
>>> Temperature.Unit.registerConverter(fahrenheit2celsius)
>>> list(Temperature.Unit.registeredConverters())
[<function celsius2fahrenheit at 0x7fab71bfef50>, <function fahrenheit2celsius at 0x7fab71bf7cf8>]
For the signature of the callables used as converters see Converter
.
>>> t27c.convert(FAHRENHEIT)
Temperature(Decimal('80.6'), Temperature.Unit('°F'))
>>> t27c.convert(FAHRENHEIT).convert(CELSIUS)
Temperature(Decimal('27'), Temperature.Unit('°C'))
Alternatively, an instance of TableConverter
can be created and
registered as converter.
The example given above can be implemented as follows:
>>> tempConv = TableConverter({(CELSIUS, FAHRENHEIT):
(Decimal('1.8'), 32)})
>>> Temperature.Unit.registerConverter(tempConv)
>>> t27c = Temperature(Decimal(27), CELSIUS)
>>> t27c.convert(FAHRENHEIT)
Temperature(Decimal('80.6'), Temperature.Unit(u'°F'))
It is suffient to define the conversion in one direction, because a reversed conversion is used automatically:
>>> t27c.convert(FAHRENHEIT).convert(CELSIUS)
Temperature(Decimal(27), Temperature.Unit(u'°C'))
2.1.4. Unit-safe computations¶
2.1.4.1. Comparison¶
Quantities can be compared to other quantities using all comparison operators defined for numbers:
>>> Length(27) > Length(9)
True
>>> Length(27) >= Length(91)
False
>>> Length(27) < Length(9)
False
>>> Length(27) <= Length(91)
True
>>> Length(27) == Length(27)
True
>>> Length(27) != Length(91)
True
Different units are taken in to account automatically, as long as they are compatible, i. e. a conversion is available:
>>> Length(27, METRE) <= Length(91, CENTIMETRE)
False
>>> Temperature(20, CELSIUS) > Temperature(20, FAHRENHEIT)
True
>>> Temperature(20, CELSIUS) > Temperature(20, KELVIN)
IncompatibleUnitsError: Can't convert 'Kelvin' to 'Degree Celsius'
Testing instances of different quantity types for equality always returns false:
>>> Length(20) == Mass(20)
False
>>> Length(20) != Mass(20)
True
All other comparison operators raise an IncompatibleUnitsError in this case.
2.1.4.2. Addition and subtraction¶
Quantities can be added to or subtracted from other quantities …:
>>> Length(27) + Length(9)
Length(Decimal(36))
>>> Length(27) - Length(91)
Length(Decimal(-64))
… as long as they are instances of the same quantity type:
>>> Length(27) + Duration(9)
IncompatibleUnitsError: Can't add a 'Length' and a 'Duration'
When quantities with different units are added or subtracted, the values are converted to the unit of the first, if possible …:
>>> Length(27) + Length(12, CENTIMETRE)
Length(Decimal('27.12'))
>>> Length(12, CENTIMETRE) + Length(17, METRE)
Length(Decimal('1712'), Length.Unit('cm'))
>>> Temperature(20, CELSIUS) - Temperature(50, FAHRENHEIT)
Temperature(Decimal('10'), Temperature.Unit(u'°C'))
… but an exception is raised, if not:
>>> Temperature(20, CELSIUS) - Temperature(281, KELVIN)
IncompatibleUnitsError: Can't convert 'Kelvin' to 'Degree Celsius'
2.1.4.3. Multiplication and division¶
Quantities can be multiplied or divided by scalars, preserving the unit:
>>> 7.5 * Length(3, CENTIMETRE)
Length(Decimal('22.5'), Length.Unit(u'cm'))
>>> Duration(66, MINUTE) / 11
Duration(Decimal(6), Duration.Unit(u'min'))
Quantities can be multiplied or divided by other quantities …:
>>> Length(15, METRE) / Duration(3, SECOND)
Velocity(Decimal(5))
… as long as the resulting type of quantity is defined …:
>>> Duration(4, SECOND) * Length(7)
UndefinedResultError: Undefined result: Duration * Length
>>> Length(12, KILOMETRE) / Duration(2, MINUTE) / Duration(50, SECOND)
UndefinedResultError: Undefined result: Velocity / Duration
>>> class Acceleration(Quantity):
... defineAs = Length / Duration ** 2
... refUnitName = 'Metre per Second squared'
...
>>> Length(12, KILOMETRE) / Duration(2, MINUTE) / Duration(50, SECOND)
Acceleration(Decimal(2))
… or the result is a scalar:
>>> Duration(2, MINUTE) / Duration(50, SECOND)
Decimal('2.4')
When cascading operations, all intermediate results have to be defined:
>>> Length(6, KILOMETRE) * Length(13, METRE) * Length(250, METRE)
UndefinedResultError: Undefined result: Length * Length
>>> class Area(Quantity):
... defineAs = Length ** 2
... refUnitName = 'Square Metre'
...
>>> Length(6, KILOMETRE) * Length(13, METRE) * Length(250, METRE)
Volume(Decimal(19500000, 3))
2.1.4.4. Exponentiation¶
Quantities can be raised by an exponent, as long as the exponent is an Integral number and the resulting quantity is defined:
>>> (5 ^ METRE) ** 2
Area(Decimal(25))
>>> (5 ^ METRE) ** 2.5
TypeError: unsupported operand type(s) for ** or pow(): 'Length' and
'float'
>>> (5 ^ METRE) ** -2
UndefinedResultError: Undefined result: Length ** -2
2.1.5. Rounding¶
The amount of a quantity can be rounded by using the standard round function.
If an Integral is given as precision, a copy of the quanitity is returned, with its amount rounded accordingly:
>>> round(Length(Decimal('17.375'), MILLIMETRE), 1)
Length(Decimal('17.4'), Length.Unit('mm'))
In addition, a unit or a quantity (of the same type) can be given to specify the requested precision. The resulting quantity will then be the integer multiple of that precision closest to the called quantity:
>>> round(Length(Decimal('17.375'), METRE), CENTIMETRE)
Length(Decimal('17.38'))
>>> round(Length(Decimal('17.375'), METRE), Length(5, CENTIMETRE))
Length(Decimal('17.4', 2))
>>> round(Length(Decimal('17.372'), METRE), Length(5, CENTIMETRE))
Length(Decimal('17.35'))
In any case the unit of the resulting quantity will be the same as the unit of the called quantity.
Note
This only applies to Python 3.x !!! In Python 2.x the standard round function tries to convert its first operand to a float and thus raises an exception when called with a quantity.
You may circumvent this by modifying the built-in round function:
try:
int.__round__
except AttributeError:
import __builtin__
py2_round = __builtin__.round
def round(number, ndigits=0):
try:
return number.__round__(ndigits)
except AttributeError:
return py2_round(number, ndigits)
__builtin__.round = round
del __builtin__
But be aware: this has side-effects if there are other classes defining a method named __round__ !!!
As an alternative the method Quantity.quantize()
can be used.
For more advanced cases of rounding the method Quantity.quantize()
can
round a quantity to any quantum according to any rounding mode:
>>> l = Length('1.7296 km')
>>> l.quantize(METRE)
Length(Decimal('1.73', 3), Length.Unit(u'km'))
>>> l.quantize(25 ^ METRE)
Length(Decimal('1.725'), Length.Unit(u'km'))
>>> l.quantize(25 ^ METRE, ROUND_UP)
Length(Decimal('1.75', 3), Length.Unit(u'km'))
2.1.6. Apportioning¶
The method Quantity.allocate()
can be used to apportion a quantity
according to a sequence of ratios:
>>> m = Mass('10 kg')
>>> ratios = [38, 5, 2, 15]
>>> portions, remainder = m.allocate(ratios)
>>> portions
[Mass(Fraction(19, 3)),
Mass(Fraction(5, 6)),
Mass(Fraction(1, 3)),
Mass(Decimal('2.5', 2))]
>>> remainder
Mass(Decimal(0, 2)))
If the quantity is quantized, there can be rounding errors causing a remainder with an amount other than 0:
>>> b = 10 ^ KILOBYTE
>>> portions, remainder = b.allocate(ratios, disperseRoundingError=False)
>>> portions
[DataVolume(Decimal('6.333375'), DataVolume.Unit(u'kB')),
DataVolume(Decimal('0.833375'), DataVolume.Unit(u'kB')),
DataVolume(Decimal('0.333375'), DataVolume.Unit(u'kB')),
DataVolume(Decimal('2.5', 6), DataVolume.Unit(u'kB'))]
>>> remainder
DataVolume(Decimal('-0.000125'), DataVolume.Unit(u'kB')))
By default the remainder will be dispersed:
>>> portions, remainder = b.allocate(ratios)
>>> portions
[DataVolume(Decimal('6.333375'), DataVolume.Unit(u'kB')),
DataVolume(Decimal('0.833375'), DataVolume.Unit(u'kB')),
DataVolume(Decimal('0.33325', 6), DataVolume.Unit(u'kB')),
DataVolume(Decimal('2.5', 6), DataVolume.Unit(u'kB'))],
>>> remainder
DataVolume(Decimal(0, 6), DataVolume.Unit(u'kB')))
As well as of numbers, quantities can be used as ratios (as long as they have compatible units):
>>> l = 10 ^ LITRE
>>> ratios = [350 ^ GRAM, 500 ^ GRAM, 3 ^ KILOGRAM, 150 ^ GRAM]
>>> l.allocate(ratios)
([Volume(Decimal('0.875', 4), Volume.Unit(u'l')),
Volume(Decimal('1.25', 3), Volume.Unit(u'l')),
Volume(Decimal('7.5', 2), Volume.Unit(u'l')),
Volume(Decimal('0.375', 4), Volume.Unit(u'l'))],
Volume(Decimal(0, 4), Volume.Unit(u'l')))
2.1.7. Formatting as string¶
Quantity
supports the standard str and unicode (Python 2.x only)
functions. Both return a string representation of the quantity’s amount
followed by a blank and the quantity’s units symbol.
Note
While the str function in Python 3.x and the unicode function in Python 2.x return the result as a unicode string, the str function in Python 2.x returns an utf8-encoded bytes string.
In addition, Quantity
supports the standard format function. The
format specifier should use two keys: ‘a’ for the amount and ‘u’ for the unit,
where ‘a’ can be followed by a valid format spec for numbers and ‘u’ by a
valid format spec for strings. If no format specifier is given, ‘{a} {u}’ is
used:
>>> v = Volume('19.36')
>>> format(v)
u'19.36 m³'
>>> format(v, '{a:*>10.2f} {u:<3}')
u'*****19.36 m³ '
2.2. Classes¶
-
class
quantity.
Quantity
¶ Base class used to define types of quantities.
Instances of
Quantity
can be created in two ways, by providing a numerical amount and - optionally - a unit or by providing a string representation of a quantity.1. Form
Parameters: - amount (number) – the numerical part of the quantity
- unit (
Unit
sub-class) – the quantity’s unit (optional)
amount must be of type number.Real or be convertable to a decimalfp.Decimal. unit must be an instance of the
Unit
sub-class corresponding to theQuantity
sub-class. If no unit is given, the reference unit of theQuantity
sub-class is used (if defined, otherwise a ValueError is raised).Returns: instance of called
Quantity
sub-class or instance of the sub-class corresponding to given unit ifQuantity
is calledRaises: 2. Form
Parameters: - qStr (unicode string) – string representation of a quantity
- unit (
Unit
sub-class) – the quantity’s unit (optional)
qStr must contain a numerical value and a unit symbol, separated at least by one blank. Any surrounding white space is ignored. If unit is given in addition, the resulting quantity’s unit is set to this unit and its amount is converted accordingly.
Returns: instance of
Quantity
sub-class corresponding to symbol in qReprRaises: QuantityError
– amount given in qStr is not a Real or Decimal number and can not be converted to a Decimal numberQuantityError
– no unit given and theQuantity
sub-class doesn’t define a reference unitQuantityError
– unit is not an instance of theUnit
sub-class corresponding to theQuantity
sub-classQuantityError
– a byte string is given that can not be decoded using the standard encodingQuantityError
– given string does not represent a QuantityIncompatibleUnitsError
– the unit derived from the symbol given in qStr is not compatible with given unit
-
classmethod
getUnitBySymbol
(symbol)¶ Return the unit with symbol symbol.
Parameters: symbol (str) – symbol to look-up Returns: Unit
sub-class, if a unit with given symbol exists within theUnit
sub-class associated with thisQuantity
sub-class, otherwise None
-
classmethod
getQuantum
(unit)¶ Return the smallest amount an instance of this
Quantity
can take for unit (return None if no quantum defined).
-
amount
¶ The quantity’s amount, i.e. the numerical part of the quantity.
-
unit
¶ The quantity’s unit.
-
convert
(toUnit)¶ Return quantity q where q == self and q.unit is toUnit.
Parameters: toUnit (Unit) – unit to be converted to Returns: resulting quantity (of same type) Return type: Quantity Raises: IncompatibleUnitsError
– self can’t be converted to unit toUnit.
-
quantize
(quant, rounding=None)¶ Return integer multiple of quant closest to self.
Parameters: quant must either be of type self.Quantity or of type self.Unit.
If no rounding mode is given, the default mode from the current context (from module decimal) is used.
Returns: Quantity
sub-class instance that is the integer multiple of quant closest to self (according to rounding mode)Raises: IncompatibleUnitsError
– quant can not be converted to self.unitTypeError
– noQuantity
orUnit
instance given
-
allocate
(ratios, disperseRoundingError=True)¶ Apportion self according to ratios.
Parameters: - ratios (iterable) – sequence of values defining the relative amount of the requested portions
- disperseRoundingError (bool) – determines whether a rounding error (if there is one due to quantization) shall be dispersed
Returns: portions of self according to ratios (list), remainder (
Quantity
) = self - sum(portions)Return type: tuple
Raises: TypeError
– ratios contains elements that can not be addedIncompatibleUnitsError
– ratios contains quantities that can not be added
-
__eq__
(other)¶ self == other
-
__hash__
()¶ hash(self)
-
__abs__
()¶ abs(self) -> self.Quantity(abs(self.amount), self.unit)
-
__pos__
()¶ +self
-
__neg__
()¶ -self -> self.Quantity(-self.amount, self.unit)
-
__add__
(other)¶ self + other
-
__radd__
(other)¶ self + other
-
__sub__
(other)¶ self - other
-
__rsub__
(other)¶ other - self
-
__mul__
(other)¶ self * other
-
__rmul__
(other)¶ self * other
-
__div__
(other)¶ self / other
-
__truediv__
(other)¶ self / other
-
__rdiv__
(other)¶ other / self
-
__rtruediv__
(other)¶ other / self
-
__pow__
(exp)¶ self ** exp
-
__round__
(precision=0)¶ Returns a copy of self with its amount rounded to the given precision.
1. Form
Parameters: precision (Integral) – number of fractional digits to be rounded to Returns: copy of self with its amount rounded to an integer multiple of 10 ** precision 2. Form
Parameters: precision ( Quantity
) – quantum of which the result has to be an integer multipleReturns: copy of self rounded to an integer multiple of precision 3. Form
Parameters: precision ( Unit
) – unit of which the result has to be an integer multiple ofReturns: copy of self rounded to integer multiple of 1 ^ precision Raises: IncompatibleUnitsError
– precision is not an Integral and can not be converted to self.unitNote: this method is called by the standard round function only in Python 3.x!
-
__repr__
()¶ repr(self)
-
__str__
()¶ str(self)
-
__format__
(fmtSpec=u'')¶ Convert to string (according to format specifier).
The specifier must be a standard format specifier in the form described in PEP 3101. It should use two keys: ‘a’ for self.amount and ‘u’ for self.unit, where ‘a’ can be followed by a valid format spec for numbers and ‘u’ by a valid format spec for strings.
-
__ge__
(other)¶ self >= other
-
__gt__
(other)¶ self > other
-
__le__
(other)¶ self <= other
-
__lt__
(other)¶ self < other
-
definition
¶ The quantity’s or units definition.
-
normalizedDefinition
¶ The quantity’s or units normalized definition.
The normalized definition defines the quantity or unit in terms of base units only.
-
class
quantity.
Unit
¶ Base class used to define types of quantity units.
Parameters: - symbol (unicode string) – unique string representation of the unit (default: None)
- name (string) – name of the unit (default: None)
- defineAs (
Quantity
sub-class or _QTerm) – definition of the unit (default: None)
If no symbol is given, but a definition, and the numerical part of that definition is None or 1, the symbol is derived from the definition.
If no symbol and no definition is given, but the corresponding
Quantity
sub-class is a derived quantity class and all its base classes have a reference unit, the symbol and the definition are derived from the class definition.If only a symbol is given and a unit with that symbol is already registered, that unit is returned.
Returns: Unit
instanceRaises: TypeError
– given symbol is not a unicode stringValueError
– no symbol was given and it could not be generatedValueError
– a unit with the given or generated symbol is already registeredValueError
– no defineAs given, but reference unit already registeredTypeError
– given defineAs does not fit theUnit
sub-class
-
classmethod
registeredUnits
()¶ Return an iterator over the units registered in cls.
-
classmethod
registerConverter
(conv)¶ Add converter conv to the list of converters registered in cls.
Does nothing if converter is already registered.
-
classmethod
removeConverter
(conv)¶ Remove converter conv from the list of converters registered in cls.
Raises ValueError if the converter is not present.
-
classmethod
registeredConverters
()¶ Return an iterator over the converters registered in ‘cls’, in reversed order of registration.
-
definition
¶ Return the definition of the unit.
-
symbol
¶ Return the units symbol, a unique string representation of the unit.
Used for the functions str, repr, format, hash and the unit registry.
-
name
¶ Return the units name.
If the unit was not given a name, its symbol is returned.
-
isRefUnit
()¶ Return True if the unit is a reference unit.
-
isBaseUnit
()¶ Return True if the unit is a base unit, i. e. it’s not derived from another unit.
-
isDerivedUnit
()¶ Return True if the unit is derived from another unit.
-
__eq__
(other)¶ self == other
-
__call__
(equiv)¶ Return scaling factor to make self equivalent to equiv.
Parameters: Returns: scaling factor so that (depending on type of equiv) factor ^ self == equiv or factor ^ self == 1 ^ equiv
Return type: number
Raises: IncompatibleUnitsError
– self and equiv are of incompatible typesUnitConversionError
– conversion factor not availableTypeError
– noQuantity
orUnit
instance given
-
__ge__
(other)¶ self >= other
-
__gt__
(other)¶ self > other
-
__le__
(other)¶ self <= other
-
__lt__
(other)¶ self < other
-
normalizedDefinition
¶ The quantity’s or units normalized definition.
The normalized definition defines the quantity or unit in terms of base units only.
-
class
quantity.
Converter
¶ A quantity converter can be any callable with a signature like conv(qty, toUnit) -> number f so that type(qty)(f, toUnit) == qty.
-
__call__
(qty, toUnit)¶ Convert a quantity’s amount to the equivalent amount for another unit.
Parameters: Returns: factor f so that f ^ toUnit == qty
Return type: number
Raises: IncompatibleUnitsError
– qty and toUnit are of incompatible typesUnitConversionError
– conversion factor not available
-
-
class
quantity.
TableConverter
(convTable)¶ Converter using a conversion table.
Parameters: convTable (dict or list) – the mapping used to initialize the conversion table Each item of the conversion table defines a conversion from one unit to another unit and consists of four elements:
- fromUnit (
Unit
sub-class): unit of the quantity to be converted - toUnit (
Unit
sub-class): target unit of the conversion - factor (number): factor to be applied to the quantity’s amount
- offset (number): an amount added after applying the factor
When a dict is given as convTable, each key / value pair must map a tuple (fromUnit, toUnit) to a tuple (factor, offset).
When a list is given as convTable, each item must be a tuple (fromUnit, toUnit, factor, offset).
factor and offset must be set so that for an amount in terms of fromUnit the eqivalent amount in terms of toUnit is:
result = amount * factor + offset
An instance of TableConverter can be called with a
Quantity
sub-class’ instance qty and aUnit
sub-class’ instance toUnit as parameters. It looks-up the pair (qty.unit, toUnit) for a factor and an offset and returns the resulting amount according to the formula given above.If there is no item for the pair (qty.unit, toUnit), it tries to find a reverse mapping by looking-up the pair (toUnit, qty.unit), and, if it finds one, it returns a result by applying a reversed formula:
result = (amount - offset) / factor
That means, for each pair of units it is sufficient to define a conversion in one direction.
An instance of TableConverter can be directly registered as a converter by calling the
Unit.registerConverter()
method of a Unit class.- fromUnit (
2.3. Functions¶
-
quantity.
getUnitBySymbol
(symbol) → unit¶ Parameters: symbol (string) – symbol to look-up Returns: Unit
sub-class if a unit with given symbol exists in one of the registered quantities’ Unit class, otherwise None
-
quantity.
generateUnits
(qCls)¶ Create and register units by combining the units of the base classes.
Parameters: qCls ( Quantity
sub-class) – derived quantity class to create units forReturns: None Raises: ValueError
– given quantity class is not a derived quantityThe function creates and registers all units from the cross-product of all units of the quantity classes the class qCls is derived from, provided that the corresponding symbol is not already registered.
-
quantity.
sum
(sequence[, start]) → value¶ Parameters: - sequence – iterable of numbers or number-like objects (NOT strings)
- start – starting value to be added (default: None)
Returns: sum of all elements in sequence plus the value of start (if not None). When sequence is empty, returns start, if not None, otherwise 0.
In contrast to the built-in function ‘sum’ this allows to sum sequences of number-like objects (like quantities) without having to provide a start value.
2.4. Exceptions¶
-
class
quantity.
QuantityError
¶ Exception raised when a quantity can not not be instanciated with the given parameters.
-
class
quantity.
IncompatibleUnitsError
(msg, operand1, operand2)¶ Exception raised when operands do not have compatible units.
-
class
quantity.
UndefinedResultError
(op, operand1, operand2)¶ Exception raised when operation results in an undefined quantity.
-
class
quantity.
UnitConversionError
(msg, fromUnit, toUnit)¶ Exception raised when a conversion between two compatible units fails.