<p>让我们看看我能不能举例说明这个动作。我对Python和<code>numpy</code>很熟悉,但是没有用过<code>sympy</code>(但是使用过其他符号代数包,比如<code>macsyma</code>)。在</p>
<p>在ipython numpy会话中:</p>
<pre><code>In [1]: def f(x,y):
...: return x**2 + x*y**2
...:
In [2]: f(1,3)
Out[2]: 10
In [3]: f(np.arange(1,4), np.arange(10,13))
Out[3]: array([101, 246, 441])
</code></pre>
<p><code>f</code>是一个python函数;它返回什么取决于输入如何处理<code>*</code>、<code>**</code>和{<cd7>}等操作。标量和数组有效。列出句柄<code>+</code>和<code>*</code>(连接、复制),但不列出<code>**</code>。在</p>
^{pr2}$
<p>定义<code>symbols</code>将创建两个新对象。它们以自己的符号方式处理<code>+</code>等。在</p>
<pre><code>In [9]: fsym = f(x,y)
In [10]: type(fsym)
Out[10]: sympy.core.add.Add
In [11]: print(fsym)
x**2 + x*y**2
</code></pre>
<p>用这两个符号对象调用<code>f</code>将创建一个新的sym对象。我也可以用其他符号和数字甚至数组的组合来调用它。在</p>
<pre><code>In [12]: f(x,0)
Out[12]: x**2
In [13]: f(1,x)
Out[13]: x**2 + 1
In [14]: f(np.arange(3), x)
Out[14]: array([0, x**2 + 1, 2*x**2 + 4], dtype=object)
</code></pre>
<p>如果我把这个<code>Add</code>对象传递给<code>sym.diff</code>,我得到一个新的<code>Add</code>对象</p>
<pre><code>In [15]: fprime = sym.diff(fsym,x)
In [16]: fprime
Out[16]: 2*x + y**2
</code></pre>
<p><code>fsym</code>和{<cd18>}都不可调用。它们不是Python函数。<code>fsym(1,2)</code>不工作。在</p>
<p>但是<code>fsym.subs</code>可用于将<code>x</code>或/和{<cd22>}替换为其他值,无论是数字还是其他符号:</p>
<pre><code>In [19]: fsym.subs(x,1)
Out[19]: y**2 + 1
In [20]: fsym.subs(y,2*x)
Out[20]: 4*x**3 + x**2
In [21]: fsym.subs([(x,1),(y,2)])
Out[21]: 5
In [22]: fprime.subs([(x,1),(y,2)])
Out[22]: 6
</code></pre>
<p><code>lambdify</code>是一个<code>sympy</code>函数,它接受一个sympy对象并返回一个Python函数,可能与<code>numpy</code>兼容`。在</p>
<pre><code>In [24]: fl = sym.lambdify((x,y), fsym, "numpy")
In [25]: fl
Out[25]: <function numpy.<lambda>>
In [26]: fl(1,2)
Out[26]: 5
In [27]: fl(np.arange(1,4), np.arange(10,13)) # cf with f(same) above
Out[27]: array([101, 246, 441])
</code></pre>
<p>这个<code>fl</code>函数与原始的<code>f</code>相似。它不完全相同,例如它有一个<code>help/doc</code>表达式。在</p>
<p>应用于<code>lambdify</code>的<code>lambdify</code>执行相同的操作,但使用了不同的符号表达式:</p>
<pre><code>In [28]: fpl = sym.lambdify((x,y), fprime, "numpy")
In [29]: fpl(1,2)
Out[29]: 6
In [30]: fpl(np.arange(1,4), np.arange(10,13))
Out[30]: array([102, 125, 150])
</code></pre>
<p>python/numpy函数或表达式与sympy函数或表达式之间的这种透明性是有限度的。另一个(删除的)答案试图探究这些问题。例如,<code>math.sin</code>,<code>numpy.sin</code>和{<cd33>}之间有区别。在</p>
<p>在这些例子中,微分是由<code>sym.diff</code>函数象征性地完成的。在</p>
<pre><code>In [35]: fsym
Out[35]: x**2 + x*y**2
In [36]: fprime
Out[36]: 2*x + y**2
</code></pre>
<p><code>sym.lambdify</code>只是将这些sympy对象之一转换为Python函数的一种方法。在</p>
<h2>trig示例</h2>
<p>从讨论中找出另一个答案</p>
<p>定义使用<code>sym</code>版本sin/cos的函数:</p>
<pre><code>In [53]: def f1(x,y):
...: return sym.sin(x) + x*sym.sin(y)
...:
In [54]: f1(x,y)
Out[54]: x*sin(y) + sin(x)
In [55]: f1(1,2)
Out[55]: sin(1) + sin(2)
In [56]: f1(1, np.arange(3)
...
SympifyError: Sympify of expression 'could not parse '[0 1 2]'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)
</code></pre>
<p>我认为这是因为<code>sym.sin(<array>)</code>不起作用;它必须是<code>np.sin(...)</code>,但这对符号无效。在</p>
<p>我们可以用符号导数:</p>
<pre><code>In [57]: sym.diff(f1(x,y),x)
Out[57]: sin(y) + cos(x)
In [58]: sym.diff(f1(x,y),y)
Out[58]: x*cos(y)
In [59]: sym.diff(sym.diff(f1(x,y),x),y)
Out[59]: cos(y)
</code></pre>
<p>再说一遍,这些a函数都没有。必须使用<code>subs</code>或{<cd23>}进行评估。在</p>
<pre><code>In [60]: f2 = sym.lambdify((x,y),f1(x,y),"numpy")
In [61]: f2
Out[61]: <function numpy.<lambda>>
In [62]: f2(1, np.arange(3))
Out[62]: array([ 0.84147098, 1.68294197, 1.75076841])
</code></pre>
<p>我可以用数组输入计算<code>f2</code>,而我不能用<code>f1</code>。推测<code>sympy</code>被<code>np.sin</code>代替{<cd33>}。在</p>
<p>事实上,当我试图用一个符号来计算<code>f2</code>时,<code>numpy</code>会抱怨:</p>
<pre><code>In [63]: f2(1,y)
...
/usr/local/lib/python3.5/dist-packages/numpy/__init__.py in <lambda>(_Dummy_30, _Dummy_31)
AttributeError: 'Symbol' object has no attribute 'sin'
In [66]: sym.diff(f2(x,y),x)
....
AttributeError: 'Symbol' object has no attribute 'sin'
</code></pre>