首页 > 解决方案 > sympy.physics.units 替换给出 TypeError

问题描述

我正在尝试使用 sympy 作为一些转换/数学代码的后端并遇到了这个问题。

from sympy.parsing.sympy_parser import parse_expr
from sympy.physics import units

type(units.newton) # -> sympy.physics.units.quantities.Quantity

parse_expr('2*Newton').subs({'Newton':units.newton}) # -> 2N
parse_expr('2*newton').subs({'newton':units.newton}) # -> 2N
parse_expr('2*n').subs({'n':units.newton}) # -> 2N
parse_expr('2*N').subs({'N':units.newton}) # -> raises TypeError below
parse_expr('N').subs() # -> raises AttributeError below
parse_expr('N') # -> <function sympy.core.evalf.N(x, n=15, **options)>

TypeError: unsupported operand type(s) for *: 'Integer' and 'function'

AttributeError: 'function' object has no attribute 'subs'

似乎 sympy 替换了 evalf.N 函数而不是提供的 units.newton 。是否有可以调整的替换顺序,或者从替换选项中删除“N”功能的方法?

编辑:已验证 evalf.N

evalf.N 函数是所使用的,但不使用 if 似乎是个问题。尝试使用.subs(..., global_dict=...)对错误没有影响。

parse_expr('N') is sympify('N') # -> True
sympify('N') is evalf.N # -> True

标签: pythonpython-3.xsympy

解决方案


从文档parse_expr中获取一个可选参数:

global_dict : dict, optional

    A dictionary of global variables. By default, this is initialized with 
    from sympy import *; provide this parameter to override this behavior 
    (for instance, to parse "Q & S").

from sympy import *N在全局命名空间中引入了一个函数,该函数parse_expr()在解析最后三个示例中的“N”时使用。

您可以在全局命名空间中重新定义“N”:

N = units.newton
parse_expr('2*N')  -> 2*newton

如果您无法重新定义“N”,则复制globals(),修改副本,并将其传递给parse_expr()

globals_with_units = dict(globals())
globals_with_units['N'] = units.newton

parse_expr('2*N', global_dict=globals_with_units)  -> 2*newton

parse_expr()还需要一个local_dict参数:

local_dict : dict, optional

    A dictionary of local variables to use when parsing.

它可用于覆盖全局命名空间中“N”的定义。

parse_expr('2*N', local_dict={'N':units.newton})  -> 2*newton

推荐阅读