我的猜测是这类似于Mathematica 的Replace method。另外this answer 对类似问题可能会有所帮助。
基本上,它将 symbol t 替换为值 0。在您的示例中,这不是很重要:
print(s.evalf().subs({t: 0}))
print(s.subs({t: 0}).evalf())
两个语句的最终值相同。但是,在计算(例如,导数)时,顺序很重要。例如,
In [76]: x=sympy.Symbol('x')
In [77]: sympy.diff(x**2, x)
Out[77]: 2*x
In [78]: sympy.diff((x**2).subs({'x':5}), x)
Out[78]: 0
In [79]: sympy.diff(x**2, x).subs({'x':5})
Out[79]: 10
在第一个示例中,x 被替换为 5 before 微分(并且 25 对 x 的导数为 0),在第二个示例中,首先计算导数 (2*x ) 然后在这个派生表达式中,符号 x 被替换为 5,所以答案是 2*5=10。
@abarnet 评论后编辑:
In [85]: import sympy
...:
...: omega, t = sympy.symbols("omega, t")
...: s = sympy.pi * sympy.cos(omega*t)
...:
...: # both result in 3.14159265358979
...: print(s.evalf().subs({t: 0}))
...: print(s.subs({t: 0}).evalf())
...: # results in 3.14159265358979*cos(omega*t)
...: print(s.evalf(subs={t: 0, omega: 1}))
...:
...:
3.14159265358979
3.14159265358979
3.14159265358979
因此,仅提供t 对sympy 来说是不够的——它无法在不知道omega 是什么的情况下评估什么是omega*0。
编辑 2:
第二个示例有效,因为评估是在 替换之后执行的,而第三个示例尝试执行 numerical 评估 使用给定的替换,但它失败了以数字方式计算表达式(没有omega),因此它以符号形式保留表达式。第一个示例也有效,因为它只是将 t 替换为 0 并简化了表达式。然而,
In [86]: s.evalf()
Out[86]: 3.14159265358979*cos(omega*t)
编辑 3:
调查代码,很明显evalf 代码(实际上是evalf_* 函数之一)尝试使用给定选项评估each argument in args 独立即subs),然后再对表达式进行求值。所以,在第一种情况下,s.evalf().subs({t: 0}),第一个eval() 不做任何事情(嗯,几乎...... - 它评估pi 到3.1415...)和subs({t: 0}) 用0 替换t 然后表达式被重新评估/简化为3.14...。在第二种情况下,首先执行替换,然后将pi 评估为3.1415...。在第三种情况下,s.args 中的每个参数都会被评估。代码在这里失败(因为它无法评估 omega 给定提供的 subs 选项)并返回输入表达式不变。
即第三个选项s.eval(subs={t: 0}) 要求定义s的所有参数。对此的检查是在here for the mul function 执行的(显然sympy master 在我安装的版本之前)。
要看到这一点,请尝试一个简单的表达式:
In [1]: import sympy
...: from sympy.core import evalf
...: t, x = sympy.symbols("t, x")
...:
...:
In [2]: (t*x).evalf(subs={t:0})
Out[2]: t*x
In [3]: evalf.evalf(t*x, 10, {t: 0})
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf(x, prec, options)
1285 rf = evalf_table[x.func]
-> 1286 r = rf(x, prec, options)
1287 except KeyError:
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf_symbol(x, prec, options)
1203 def evalf_symbol(x, prec, options):
-> 1204 val = options['subs'][x]
1205 if isinstance(val, mpf):
KeyError: 'subs'
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf(x, prec, options)
1292 xe = x._eval_evalf(prec)
-> 1293 re, im = xe.as_real_imag()
1294 if re.has(re_) or im.has(im_):
AttributeError: 'NoneType' object has no attribute 'as_real_imag'
During handling of the above exception, another exception occurred:
NotImplementedError Traceback (most recent call last)
<ipython-input-3-e075388b139d> in <module>()
----> 1 evalf.evalf(t*x, 10, {t: 0})
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf(x, prec, options)
1284 try:
1285 rf = evalf_table[x.func]
-> 1286 r = rf(x, prec, options)
1287 except KeyError:
1288 try:
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf_mul(v, prec, options)
536 from sympy.core.numbers import Float
537 for arg in args:
--> 538 arg = evalf(arg, prec, options)
539 if arg[0] is None:
540 continue
~/.../lib/python3.5/site-packages/sympy/core/evalf.py in evalf(x, prec, options)
1308 r = re, im, reprec, imprec
1309 except AttributeError:
-> 1310 raise NotImplementedError
1311 if options.get("verbose"):
1312 print("### input", x)
NotImplementedError:
In [4]: