Python 实现物理单位转化 - physics.py 平时处理数据时有一个需求是要转化物理单位,比如标准压强单位是帕斯卡(Pa),但其实用的比较多的是 bar(相当于0.1 mPa),atm(标准大气压),psi(外国用的比较多,磅每平方英寸)。要想实现这些单位的标准化,最简单的方法就是编写些公式,比如我想让他们全都转换成标准大气压,根据下面公式可以开始写函数:
1 bar = 0.1mPa = 0.9869 atm
1 2 3 4 5 6 def to_atm (value, unit ): if unit == 'bar' : return value / 1.01325 elif unit == 'pa' : return value / 100000 / 1.01325 ...
这样写临时用自然没有问题,但一来觉得有大量冗余代码(比如上述案例中 1.01325 是个标准大气压的常数,二来如果下次我想要用 kPa 或者 mPa 作为标准单位,则又要写一个函数,显然非常笨拙。
在网上找了一番后发现有个非常精简(仅一个 Python 文件)且好用的 Python 库 ipython_physics ,从名字可以看出该库最初的目的是作为 IPython(或 Jupyter)的插件。
具体使用时这样就行:
1 2 3 4 5 6 from ipython_physics import Qa = Q('1 bar' ) print(a.to('atm' )) print(a.to('atm' ).value)
该库的类主要借鉴了 PhysicalQuantities 中的 quantity.py 和 unit.py ,并往里面加了大量的物理单位,其中就包含了我需要使用到的压力相关的物理单位:
1 2 3 4 5 6 7 _addUnit("bar" , "1.e5*Pa" , "bar (cgs unit)" ) _addUnit("mbar" , "1.e2*Pa" , "millibar" ) _addUnit("kbar" , "1.e8*Pa" , "kilobar" ) _addUnit("atm" , "101325.*Pa" , "standard atmosphere" ) _addUnit("torr" , "atm/760" , "torr = mm of mercury" ) _addUnit("psi" , "6894.75729317*Pa" , "pounds per square inch" )
咱们来看看它实现物理量转换的核心函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def _convertValue (value, src_unit, target_unit ): (factor, offset) = src_unit.conversion_tuple_to(target_unit) return (value + offset) * factor class PhysicalQuantity (object ): ... def to (self, *units ): units = [_findUnit(x) for x in units] if len (units) == 1 : unit = units[0 ] value = _convertValue(self.value, self.unit, unit) return self.__class__(value, unit) ... class PhysicalUnit (object ): ... def conversion_tuple_to (self, other ): if self.powers != other.powers: raise UnitError("Incompatible units" ) factor = self.factor / other.factor offset = self.offset - (other.offset * other.factor / self.factor) return (factor, offset)
假设是这个过程: Q(’1 pa’).to(’atm’)
首先就是得到系数, factor = (pa).factor / (atm).factor
pa 的系数就是标准物理量 1 Pa,而 atm 则是 101325.*Pa,因此算出 factor = 1/101325,就很容易得到结果。
最后是一个我在这个过程中踩的一个坑,有一个通俗的压力单位是 kg/cm2,甚至更简单点用“公斤”描述压强,但其实这个不是一个标准的压力单位,kg 是质量单位,而压力单位是牛顿,因此需要乘以一个重力才行,否则是不能识别的。
1 2 3 4 5 6 7 a = Q('10 kg/cm^2' ) a.to('atm' ) g0=Q("9.80665 m/s**2" ) (a * g0).to('atm' )
这样就完成了所有通俗压强单位到标准大气压的单位转换。