python - 装饰器未返回预期单位的值

标签 python pint

以下代码使用 pint将质量流量转换为体积流量。为了将质量转换为体积,必须计算气体的密度。计算返回所需单位的正确值。

import pint
ureg = pint.UnitRegistry()
Q_ = ureg.Quantity


def density(T):
    R = 287 * ureg('J/kg/K')
    P = 101325 * ureg('Pa')
    return (P / R / T.to(ureg.kelvin)).to(ureg('kg/m^3'))


@ureg.wraps(ret='m^3/sec', args=['kg/sec', 'kg/m^3'])
def volumetric_flow_rate(mass_flow_rate, rho):
    return mass_flow_rate / rho


mfr = 1 * ureg('kg/s')
temperature = Q_(25, ureg.degC)

rho = density(temperature)
print(rho)
# 1.1841314120000166 kilogram / meter ** 3

v = volumetric_flow_rate(mfr, rho)
print(v)
# 0.8445008635578583 meter ** 3 / second

但是,当我申请使用@ureg.wraps密度函数上的装饰器以与volumetric_flow_rate相同的方式使用,值是正确的,但单位不是所需的单位。

@ureg.wraps(ret='kg/m^3', args=['K'])
def density(T):
    R = 287 * ureg('J/kg/K')
    P = 101325 * ureg('Pa')
    return P / R / T

rho = density(temperature)
print(rho)
# 1.1841314120000166 kelvin * kilogram * pascal / joule kilogram / meter ** 3

v = volumetric_flow_rate(mfr, rho)
print(v)
# 0.8445008635578583 joule / kelvin / kilogram / pascal meter ** 3 / second

以下版本的装饰器对于密度函数都产生相同的结果(不正确的返回单位):

@ureg.wraps(ret='kg/m^3', args='K')
@ureg.wraps(ret='kg/m^3', args=['K'])
@ureg.wraps(ret='kg/m^3', args=ureg.kelvin)
@ureg.wraps(ret='kg/m^3', args='K', strict=True)
@ureg.wraps(ret='kg/m^3', args=['K'], strict=True)
@ureg.wraps(ret='kg/m^3', args=ureg.kelvin, strict=True)
@ureg.wraps(ret='kg/m^3', args='K', strict=False)
@ureg.wraps(ret='kg/m^3', args=['K'], strict=False)
@ureg.wraps(ret='kg/m^3', args=ureg.kelvin, strict=False)

以下版本的装饰器引发错误

@ureg.wraps(ret=ureg('kg/m^3'), args=ureg.kelvin)

TypeError: wraps 'ret' argument must by of type str or Unit, not <class 'pint.quantity.build_quantity_class.<locals>.Quantity'> (1.0 kilogram / meter ** 3)

有了这个错误消息,我 defined a custom unit 质量流量

ureg.define('mass_flow = 1 * kg / m^3')
print(ureg.mass_flow)
# mass_flow
print(type(ureg.mass_flow))
# <class 'pint.unit.build_unit_class.<locals>.Unit'>
print(1 * ureg.mass_flow)
# 1 mass_flow

以下装饰器不会引发错误,但它们仍然会产生错误的单位(尽管现在使用 mass_flow“单位”。

@ureg.wraps(ret=ureg.mass_flow, args='K')
@ureg.wraps(ret='mass_flow', args='K')
# 1.1841314120000166 kelvin * kilogram * pascal / joule mass_flow

我尝试的最后一次尝试是在函数外部定义 RP。没想到它会改变答案,预期是正确的。

R = 287 * ureg('J/kg/K')
P = 101325 * ureg('Pa')
@ureg.wraps(ret='kg/m^3', args='K')
def density(T):
    return P / R / T

问题:

如何以与 volumetric_flow_rate 函数类似的方式定义 密度 函数的装饰器,以便函数主体更清晰并且不需要我进行内部单位转换吗?

此外,如果 volumetric_flow_rate 函数具有复杂的返回单位 m^3/sec 为什么 kg/m^3 不起作用密度函数?

Python 3.7.0,品脱0.10.1

最佳答案

Pint 似乎会在进入函数之前去除所有单位,然后在函数结束时应用单位。因此,以下任一方法都有效。

@ureg.wraps(ret='kg/m^3', args=['K', 'Pa', 'J/kg/K'])
def density(T, P=101325 * ureg.Pa, R=287 * ureg('J/kg/K')):
    return P / R / T

@ureg.wraps(ret='kg/m^3', args=['K', 'Pa', 'J/kg/K'], strict=False)
def density(T, P=101325, R=287):
    return P / R / T

关键是要确保函数中的所有内容都是无量纲的。如果您在 @ureg.wraps 中调用另一个函数装饰函数,该函数返回一个维度数量,将其转换为所需的单位,然后使用 .magnitude 去除单位。属性。

关于python - 装饰器未返回预期单位的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60266835/

相关文章:

python - 为什么每次保存模型时哈希值都会改变?

python - 在单元测试中将 JSON 发布到 Flask 端点时出现错误请求

python - 如何将外部文件中的分数添加到字典中并对它们进行从 1 到 10 的排名

python - SymPy 中的维度分析

python - 为什么品脱需要单位登记?

python - 从 pandas groupby 返回聚合数据框

python - ._meta 的逆得到反向 FK 类