Это не особенно приятно или обобщать, но вы можете сделать следующее, чтобы преобразовать любой Mul
в VectorMul
, когда это необходимо (и оставить его как Mul
в противном случае):
import sympy as sp
from sympy.vector import CoordSys3D
from sympy.core.mul import Mul
N = CoordSys3D('N')
def multiply_args(obj):
'''Gets the result of multiplying all of the Mul's args together.'''
if not isinstance(obj, Mul):
raise ValueError('Input must be an instance of Mul')
args = obj.args
prod = args[0]
for e in args[1:]:
prod = prod * e
return prod
Q, eps, zhat = sp.symbols('Q \epsilon_0 \\hat{\\mathbf{z}}')
vec = N.k
term = Q*eps*zhat
sub_result = term.subs(zhat, vec)
sub_result = multiply_args(sub_result)
Причина, по которой это необходимо, заключается в том, что subs
, метод, принадлежащий классу Basic
, просто просматривает все аргументы (например, Q
, eps
, zhat
) объекта Mul
( term
) и заменяет каждый, который соответствует цели замены, и дает результат как Mul
, но с измененным списком args
(т.е. zhat
был заменен на vec
). Он не выполняет никакой дальнейшей оценки результата и оставляет аргумент как Mul
.
Чтобы преобразовать его в VectorMul
, вы можете просто вручную перемножить полученные аргументы вместе, как вы это делали. чтобы получить out_ideal
. Все, что делает multiply_args
, - это вручную умножает аргументы вместе, что затем увеличивает до VectorMul
, если какой-либо из аргументов равен Vector
. Очевидно, это работает только потому, что вы знаете, что начали с Mul
; вам нужно будет обобщить это, чтобы иметь дело с другими типами, если вам нужно.
Может, стоит добавить функцию reqeust в репозиторий SymPy Github для этой функции.