physipy: 使 Python 具有单位感知

📅 发布时间:2026/7/10 21:01:14 👁️ 浏览次数:
physipy: 使 Python 具有单位感知
原文towardsdatascience.com/physipy-make-python-unit-aware-846162522889你是否曾经用 Python 进行过工程/科学计算最终发现自己迷失或困惑于变量的单位比如“那是米还是毫米的值”或者你意识到在某个时刻你添加了一个电流和一个电阻——这是不可能的就像每个物理老师都说过的一样你不能把胡萝卜和西红柿加在一起。好吧**physipy**正是为了解决这类问题而存在的。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/48a489520af593c6f986187d72cd631c.png由Artturi Jalli在Unsplash上的照片目录· 什么是 physipy · 一次一个示例理解 physipy∘使用 physipy 计算身体质量指数 BMI ∘ 使用 NumPy 数组牛顿运动定律 ∘ 使用 NumPy 函数的欧姆定律 ∘ 使用 favunit 计算常见粒子的爱因斯坦质能等价 ∘ 使用内置 favunit 进行自由落体 ∘ 使用 Matplotlib 绘制物体位置和速度· 总结所有图片均为作者所有。什么是 physipy***physipy***是一个轻量级的包它允许你非常容易地定义和声明物理单位并跟踪所有变量的单位。换句话说你永远不需要在变量后加上相应的单位例如my_height_cm将变成my_height如果你试图把胡萝卜和西红柿加在一起将会抛出一个异常。physipy为科学/工程工作提供了很好的功能它与 NumPy 完美集成提供了 Pandas 扩展完整的文档与 Matplotlib 无缝工作并为 jupyter 提供了(ipy)小部件。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/50b8975149fd05132af07cb8b09828fc.png导入米和秒并开始使用具有单位感知的变量。为了完全透明我是 physipy 的创建者。另外请注意physipy 在MIT 许可证下。一次一个示例理解 physipy在这篇第一篇文章中我们将看到如何使用physipy特别是它如何与 NumPy 和 Matplotlib 很好地集成通过一些基本的示例。这些示例的目的是按顺序阅读因为在阅读过程中会逐渐添加概念和工具。另一方面它们都旨在非常简单且注释良好所以即使直接跳到最后一个也能理解。您也可以直接访问 Physipy 的文档或 GitHub 上的项目仓库。physipy : 使 python 具有单位感知功能GitHub – mocquin/physipy: 一个透明的处理物理量如 2…要安装 physipy您可以使用 pypi 通过简单的命令行pip install physipy或者如果您更喜欢从 GitHub 下载最新版本您可以在本地下载并解压缩包或者使用以下命令克隆 git 仓库git clone https://github.com/mocquin/physipy使用 physipy 计算身体质量指数 BMI如您所知一个常见的健康指标是身体质量指数。正如维基百科所述As wikipedia states体质指数BMI是从一个人的质量体重和身高推导出的一个值。BMI 定义为身体质量除以身体高度的平方并以 kg/m2 的单位表示由千克kg的质量和米m的高度组成。让我们看看没有 physipy 的代码会是什么样子#### BMI example, without physipy# no physipy → we need to keep track of the unit everywheremy_weight_kg75my_height_m1.89defbmi_calculator(weight_kg,height_m):Compute Body-Mass-Index from weight and height.returnweight_kg/height_m**2print(bmi_calculator(my_weight_kg,my_height_m))# notice that the output is pure, unit-less number, while it is actually kg-per-meter-squared# 20.99605274208449现在让我们看看使用 physipy 的代码是什么样的fromphysipyimportkg,m# define physical quantities that are unit awaremy_weight75*kg my_height1.89*mdefbmi_calculator(weight,height):Compute Body-Mass-Index from weight and height.returnweight/height**2print(bmi_calculator(my_weight,my_height))# 20.99605274208449 kg/m**2注意代码变化有多小我们可以在变量名称中去除任何单位后缀而不会失去对它们的跟踪。另一方面我们可以看到变量的值是明确定义的使用了命名单位。另一个很好的特性是返回的输出仍然附有适当的单位在这种情况下是kg/m**2。好处在于我们可以使用任何单位而不用担心任何转换所有转换都由 Physipy 在后端完成。例如假设你记录了身高厘米和体重克。# retrieve the unitsfromphysipyimportunits# units is just a dictcmunits[cm]gunits[g]print(bmi_calculator(75000*g,189*cm))# 20.99605274208449 kg/m**2因此我们得到了相同的输出值同时我们能够指定变量在其他单位中。使用 numpy 数组进行牛顿运动定律我们在这里演示如何仅使用常规乘法运算符类似于浮点数和整数将单位附加到常规 NumPy 数组上importnumpyasnpfromphysipyimportm,kg,s mnp.array([10,20,30])*kg# massa2*m/s**2# acceleration# Calculate force using Newtons Second Law : force mass * accelerationFm*aprint(F)# [ 200\. 800\. 1800.] kg**2/s**2# 1 kg**s/s**2 is equivalent to 1 Newton欧姆定律与 NumPy 函数使用 NumPy 和 Physipy 几乎可以与所有 NumPy 的函数一起工作。在这里我们可以使用具有单位感知值的 NumPy 函数并且返回的数组仍然具有正确的单位。importnumpyasnpfromphysipyimportunits Vunits[V]ohmunits[ohm]V12*V# voltageRnp.arange(1*ohm,5*ohm)# array with unit ohm# Calculate current using Ohms LawIV/Rprint(I)# [12\. 6\. 4\. 3.] A# If for some reason you forgot the unit of I, physipy knows and attaches# it to I for you - you get an output in Amps for free !对于常见粒子使用 favunit 的爱因斯坦质量-能量等价对于常见粒子使用 Favunit 在这个例子中我们介绍了任何单位感知对象的.favunit属性这意味着这个变量的“首选单位”。这个单位将用于打印变量。在国际单位制中能量的标准单位是焦耳等于 1 kg*m2/s2。importnumpyasnpfromphysipyimportconstants,kg,units# constants is just a dict of physical constantscconstants[c]Junits[J]massesnp.array([9.1093837E-31,# mass of electron1.673E-27,# mass of proton1.675E-27,# mass of neutron])*kg# Calculate energy using Einsteins equationEmasses*c**2# indexing works just as usual, with the added output energy unitprint(E[0])# enery for proton : 8.187105775475753e-14 kg*m**2/s**2print(E)# [8.18710578e-14 1.50361741e-10 1.50541492e-10] kg*m**2/s**2# changing the display unit to JouleE.favunitJprint(E[0])# 8.187105775475753e-14 Jprint(E)# [8.18710578e-14 1.50361741e-10 1.50541492e-10] J如您所见相同的变量favunit可以随意修改以更改其字符串表示形式。Physipy 的酷之处在于这个.favunit属性仅用于打印目的实际的“真实”值和物理单位kg*m2/s2存储在后端。使用内置的 favunit 进行自由落体在这个例子中我们正在模拟一个物体从 100 米的初始高度自由落体。我们使用自由落体的运动方程hh0−1/2gt²其中 h 是物体在时间 t 的高度h0 是初始高度g 是重力加速度t 是时间。我们使用这个例子来展示如何设置favunit—— 变量用于打印的单位可以是函数中的“手动”设置也可以使用set_favunit装饰器。让我们先看看如何手动设置首选单位importnumpyasnpfromphysipyimportm,s,units cmunits[cm]# we are using cm as the favunit# Constantsinitial_height100*m# Initial height of the objectgravity9.81*m/s**2# Acceleration due to gravity# Time samplestime_samplesnp.linspace(0,3,50)*s# Time samples from 0 to 5 secondsdefcalculate_height(time_samples):heigthinitial_height-0.5*gravity*time_samples**2heigth.favunitcmreturnheigth# Calculate heights for each time sampleheightscalculate_height(time_samples)# Print time samples and corresponding heightsfort,hinzip(time_samples,heights):print(fTime:{t}, Height:{h})# Time: 0.0 s, Height: 10000.0 cm# ...# Time: 3.0 s, Height: 5585.5 cm虽然设置高度favunit的方法很简单但它与实际的数学计算无关。另一种方法是使用set_favunit装饰器。所以以下两个片段是等效的手动设置 favunitdefcalculate_height(time_samples):heigthinitial_height-0.5*gravity*time_samples**2heigth.favunitcmreturnheigth在这里使用set_favunit装饰器fromphysipyimportset_favunitset_favunit(cm)defcalculate_height(time_samples):heigthinitial_height-0.5*gravity*time_samples**2returnheigth使用set_favunit装饰器可能更受欢迎因为它将计算逻辑和单位打印分离开来。使用 Matplotlib 绘制物体的位置和速度在这个例子中我们正在可视化物体在重力影响下的运动。具体来说我们正在绘制其运动的两个重要方面位移和速度随时间的变化。重要的语句是调用setup_matplotlib()这样 Matplotlib 就会意识到 Physipy并且默认情况下会在绘制单位感知对象时设置相应的单位。换句话说你可以去掉set_xlabel(s)或set_ylabel(km)来指定单位physipy会自动完成这项工作。importnumpyasnpimportmatplotlib.pyplotaspltfromphysipyimportunits,s,setup_matplotlib,constants cmunits[cm]# centimetermsunits[ms]# millisecondgconstants[g]# this makes matplotlib aware of physipysetup_matplotlib()timenp.linspace(0,10,100)*s# Time valuestime.favunitms velocityg*time# Velocity as a function of time (assuming constant acceleration)displacement0.5*g*time**2# displace from origin positiondisplacement.favunitcm# Plottingfig,axplt.subplots(figsize(10,4))ax.plot(time,displacement,labelDisplacement,colorblue)ax2ax.twinx()ax2.plot(time,velocity,labelVelocity,linestyle - ,colorred)https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/52357ccf04fe088d66f79b45995d90fc.png注意轴标签上添加了一些单位但没有显式调用 set_xlabel/set_ylabel。总结希望这些例子能帮助你理解如何使用 physipy 的基础知识。你应该记住以下事项使用 physipy 最简单的方法是导入一些单位/常量这些单位/常量存储在经典的 Python 字典中使用from physipy import units, constants。注意国际单位制Système International units可以直接使用from physipy import m, s, kg。要定义单位感知变量只需将值乘以单位即可例如heights np.linspace(1, 50)*km。几乎所有的 numpy 函数都适用于单位感知数组例如你可以简单地使用np.max(heights)找到高度数组中的最大值返回的值将是50000 m。默认情况下单位感知值将使用 SI 单位打印例如焦耳将打印为kg*m**2/s**2。如果你想使用特定的单位只需设置favunit属性heights.favunit mm你可以使用from physipy import setup_matplotlib和setup_matplotlib()来使 matplotlib 识别 physipy 并处理单位。从那时起任何图表都会将单位添加到轴标签中。physipy 的优点是它轻量级简单的示例源代码简单它与 numpy 和 matplotlib 高度集成。我们稍后会看到它也是一个处理 Python 中单位的快速包归功于其轻量级结构因此开销小。它还提供了pandas 扩展和ipywidgets for jupyter/notebooks。在下一篇文章中我们将稍微深入探讨 physipy介绍 physipy 的 2 个也是唯一 2 个重要类即Dimension和Quantity。你可以在项目的文档中找到更多示例和大量信息physipy : 使 Python 具有单位感知你可能喜欢我之前的一些帖子我写关于 Python、机器学习/数据科学、信号处理、数值技术的内容Sklearn 教程科学/数值 Python数据科学和机器学习时间序列的傅里叶变换