首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在预期单位中未返回值的装饰器

在预期单位中未返回值的装饰器
EN

Stack Overflow用户
提问于 2020-02-17 16:36:50
回答 1查看 84关注 0票数 1

下面的代码使用品脱将质量流转换为体积流。要从质量转化为体积,必须计算气体的密度。计算返回所需单位中的正确值。

代码语言:javascript
复制
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相同的方式在density函数上使用volumetric_flow_rate装饰符时,值是正确的,但这些单位不是所需的单位。

代码语言:javascript
复制
@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

以下版本的装饰器都会为density函数产生相同的结果(不正确的返回单位):

代码语言:javascript
复制
@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)

以下版本的装饰程序会引发错误

代码语言:javascript
复制
@ureg.wraps(ret=ureg('kg/m^3'), args=ureg.kelvin)

'pint.quantity.build_quantity_class..Quantity'>:包装'ret‘参数必须是str或Unit类型,而不是

带着这条错误消息,我定义自定义单元 mass_flow

代码语言:javascript
复制
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“单元”)。

代码语言:javascript
复制
@ureg.wraps(ret=ureg.mass_flow, args='K')
@ureg.wraps(ret='mass_flow', args='K')
# 1.1841314120000166 kelvin * kilogram * pascal / joule mass_flow

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

代码语言:javascript
复制
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

问题:

如何以类似于density函数的方式定义volumetric_flow_rate函数的装饰符,从而使函数的主体更加简洁,而不需要进行内部单元转换?

此外,如果volumetric_flow_rate函数有一个复杂的返回单元m^3/sec,为什么kg/m^3不适用于density函数?

Python 3.7.0,Pint 0.10.1

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-18 01:36:46

品脱显示在进入函数之前将所有单位剥离,然后在功能结束时应用单位。因此,以下任何一项工作。

代码语言:javascript
复制
@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属性剥离这些单元。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60266835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档