SymPy 对象分类

有多种方法可以对 SymPy 对象进行分类。

与 Python 中的任何其它对象一样,SymPy 表达式是类的实例。您可以使用内置的 \(type()\) 函数获取对象的类,并使用 \(isinstance()\) 函数进行检查。

>>> from sympy import Add
>>> from sympy.abc import x,y
>>> type(x + y)
<class 'sympy.core.add.Add'>
>>> isinstance(x + y, Add)
True

类仅表示对象的编程结构,并不区分它们之间的数学差异。例如,数字的积分和矩阵的积分都属于 \(Integral\) 类,尽管前者是数字,后者是矩阵。

>>> from sympy import MatrixSymbol, Integral
>>> A = MatrixSymbol('A', 2, 2)
>>> type(Integral(1, x))
<class 'sympy.integrals.integrals.Integral'>
>>> type(Integral(A, x))
<class 'sympy.integrals.integrals.Integral'>

类型

类型表示表达式所代表的数学对象。您可以使用 \(.kind\) 属性获取表达式的类型。

>>> Integral(1, x).kind
NumberKind
>>> Integral(A, x).kind
MatrixKind(NumberKind)

此结果表明 \(Integral(1, x)\) 是数字,而 \(Integral(A, x)\) 是具有数字元素的矩阵。

由于类无法保证捕捉到这种差异,因此对象的类型非常重要。例如,如果您正在构建一个仅针对数字设计的函数或类,您应该考虑使用 \(NumberKind\) 过滤参数,以防止用户无意中传递不支持的对象,例如 \(Integral(A, x)\)

为了提高性能,集合理论没有在类型系统中实现。例如,

\(NumberKind\) 无法区分实数和复数。

>>> from sympy import pi, I
>>> pi.kind
NumberKind
>>> I.kind
NumberKind

SymPy 的 \(Set\) 和类型不兼容。

>>> from sympy import S
>>> from sympy.core.kind import NumberKind
>>> S.Reals.is_subset(S.Complexes)
True
>>> S.Reals.is_subset(NumberKind)
Traceback (most recent call last):
...
ValueError: Unknown argument 'NumberKind'

集合和假设

如果您希望以严格的数学方式对对象进行分类,则可能需要使用 SymPy 的集合和假设。

>>> from sympy import ask, Q
>>> S.One in S.Reals
True
>>> ask(Q.even(2*x), Q.odd(x))
True

有关更多信息,请参阅 \(assumptions\) 模块和 \(sets\) 模块。

func

\(func\) 是对象的头部,用于递归遍历表达式树。

>>> Add(x + y).func
<class 'sympy.core.add.Add'>
>>> Add(x + x).func
<class 'sympy.core.mul.Mul'>
>>> Q.even(x).func
<class 'sympy.assumptions.assume.AppliedPredicate'>

正如您所见,结果头部可能是一个类或另一个 SymPy 对象。当您使用此属性对对象进行分类时,请牢记这一点。有关详细信息,请参阅 高级表达式操作