装饰器未返回预期单位的值
Decorator Not Returning Value in Expected Units
以下代码使用 pint 将质量流量转换为体积流量。要将质量转换为体积,必须计算气体的密度。计算 return 是所需单位的正确值。
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
然而,当我申请以与 volumetric_flow_rate
相同的方式在 density
函数上使用 @ureg.wraps
装饰器时,值是正确的,但单位不是所需单位。
@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
函数产生相同的结果(不正确的 return 单位):
@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 mass_flow
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
"units".
@ureg.wraps(ret=ureg.mass_flow, args='K')
@ureg.wraps(ret='mass_flow', args='K')
# 1.1841314120000166 kelvin * kilogram * pascal / joule mass_flow
我尝试的最后一次尝试是在函数外定义 R
和 P
。没想到竟然改答案了,果然没有错。
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
函数的方式为 density
函数定义装饰器,以便函数体更简洁并且不需要我做内部单元转换?
此外,如果 volumetric_flow_rate
函数有一个复杂的 return 单位 m^3/sec
为什么 kg/m^3
对 density
函数不起作用?
Python3.7.0,Pint0.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
修饰函数中调用另一个函数,并且该函数 returns 是量纲,请将其转换为所需的单位,然后使用 .magnitude
属性去除单位。
以下代码使用 pint 将质量流量转换为体积流量。要将质量转换为体积,必须计算气体的密度。计算 return 是所需单位的正确值。
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
然而,当我申请以与 volumetric_flow_rate
相同的方式在 density
函数上使用 @ureg.wraps
装饰器时,值是正确的,但单位不是所需单位。
@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
函数产生相同的结果(不正确的 return 单位):
@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 mass_flow
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
"units".
@ureg.wraps(ret=ureg.mass_flow, args='K')
@ureg.wraps(ret='mass_flow', args='K')
# 1.1841314120000166 kelvin * kilogram * pascal / joule mass_flow
我尝试的最后一次尝试是在函数外定义 R
和 P
。没想到竟然改答案了,果然没有错。
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
函数的方式为 density
函数定义装饰器,以便函数体更简洁并且不需要我做内部单元转换?
此外,如果 volumetric_flow_rate
函数有一个复杂的 return 单位 m^3/sec
为什么 kg/m^3
对 density
函数不起作用?
Python3.7.0,Pint0.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
修饰函数中调用另一个函数,并且该函数 returns 是量纲,请将其转换为所需的单位,然后使用 .magnitude
属性去除单位。