|
|
Subscribe / Log in / New account

Native Python support for units?

Native Python support for units?

Posted Jul 14, 2022 7:37 UTC (Thu) by taladar (subscriber, #68407)
In reply to: Native Python support for units? by k8to
Parent article: Native Python support for units?

That said it would still be valuable to make sure the units in any calculation work out properly even with currencies, e.g. that I multiply my value in Euro with the Dollars/Euro value to get Dollars, not with the Dollars/Yen value.


to post comments

Native Python support for units?

Posted Jul 14, 2022 8:07 UTC (Thu) by farnz (subscriber, #17727) [Link] (2 responses)

That's an important point. There are two uses of units in a program:

  1. To encode the correct scale factors to your numbers so that you can combine arbitrary units and get the right answer (e.g. 3 feet times 10 Newtons times 1,200 rotations per minute is how many metric horsepower?)
  2. As a type system to stop you making nonsense combinations of units (e.g. if I know something's price in USD/feet, I can't multiply by the volume of the object I'm building to get a price in JPY, because the units don't work out).

The first is very Pythonic in nature - the second amounts to a static type system for units, and I'm not sure how that fits in with the dynamic typing Python prefers.

Native Python support for units?

Posted Jul 15, 2022 19:09 UTC (Fri) by NYKevin (subscriber, #129325) [Link]

Python already *sort of* supports (2) with NewType, see https://docs.python.org/3/library/typing.html#distinct

The problem with the existing support is that, for example, [length] + [length] should be of type [length], but if you try to do that with NewType, you just get back float or int (types aren't preserved across binary operations). That's fixable for addition and subtraction relatively easily (define and type hint appropriate dunder methods), but it would be more complicated in the case of multiplication and division, because Python's generics are insufficiently advanced to support e.g. [length] / [time] = [speed]. You could hard-code all of those conversions one at a time, and perhaps generate the code somehow, but a lot of fundamental constants have weird units that wouldn't necessarily have a "standard" interpretation, such as the Boltzmann constant ([length]^2 * [mass] * [time]^-2 * [temperature]^-1), and it would not be fun to hard code those as well.

Ideally, a unit library should allow you to multiply and divide whatever by whatever and just make sense of it, but that would require the ability to put non-type arguments into Python's generics. Then we could express the Boltzmann constant's type as something like Quantity[2, 1, -2, 0, -1, 0, 0], where each number indicates the exponent of a given unit. Right now, Python does not let you do that (to the best of my understanding), because the arguments have to be types, not integers.

However, this also raises more philosophical problems. There are seven base units in the SI system, so one might assume that Quantity should have a fixed arity of seven exponents. However, the SI system doesn't cover many commonly-used units, such as bytes. There are also logarithmic units such as the bel (or decibel) and the cent (used in music theory, not to be confused with various currencies), which are subject to more complicated coherence rules than typical (linear) units. And the radian is officially a derived unit of the form m/m (so that the equation s=rθ) is valid, but that would just simplify to dimensionless unless you special-case it somehow (the steradian has the same problem).

Native Python support for units?

Posted Jul 24, 2022 23:41 UTC (Sun) by pdundas (guest, #15203) [Link]

It seems to me that units are not a property of a variable, but of a number. Perhaps that is more pythonic - or more amenable to duck typing (if a value walks and talks like a length... it's a length). Python already has the ability not to add incompatible types at run time (like a variable representing a string to a variable representing an integer). So if you were using numbers with types, it would be just as pythonic to fail to add 5 metres to 30 seconds.

Interestingly you can *multiply* or *divide* distance and time, giving a quantity with a complex unit - speed might be 5m/30s (or 10m/minute, or some other number in furlongs per microfortnight). All kinds of weird and wonderful composite units are available - as some posters mentioned earlier. Or consider electrical units - Amps are Coulombs per second, Volts are Joules per Coulomb, and Watts are Joules per second - or something like that - it's been a while. Which raises interesting possibilities for *display* of numbers with units attached, when they need to be scaled, or converted between families of units that measure the same thing, or expressed (as for Current) in a particular way.

As for how to do that in Pythin, I've no idea. But it's a fascinating problem.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds