在我的程序中使用"from __future__ import division",但未能加载
我写了一个Python 2的程序,用来做牛顿法的计算,解决我的数学问题集。这个程序运行得很好,但我不知道为什么,当我在ipython中用%run -i NewtonsMethodMultivariate.py
加载它时,Python 3的除法功能没有被引入。我知道这一点是因为在加载我的程序后,输入x**(3/4)
时,它返回的是“1”。而在我手动引入新的除法功能后,x**(3/4)
就保持为x**(3/4)
,这才是我预期的结果。为什么会这样呢?
# coding: utf-8
from __future__ import division
from sympy import symbols, Matrix, zeros
x, y = symbols('x y')
X = Matrix([[x],[y]])
tol = 1e-3
def roots(h,a):
def F(s):
return h.subs({x: s[0,0], y: s[1,0]})
def D(s):
return h.jacobian(X).subs({x: s[0,0], y: s[1,0]})
if F(a) == zeros((2,1)):
return a
else:
while (F(a)).norm() > tol:
a = a - ((D(a))**(-1))*F(a)
print a.evalf(10)
我本来想用Python 3来避免这个问题,但我的Linux系统只提供了Python 2的SymPy库。感谢任何能提供帮助的人。
另外,如果有人好奇的话,我还没有把这个脚本扩展到nxn的雅可比矩阵,只处理了2x2的情况。此外,我在处理2x2的零矩阵时,选择了切片,而不是使用(感谢eryksun纠正了我的符号,这解决了zeros函数的问题。)zeros(2,1)
这个命令,因为我机器上安装的SymPy 0.7.1抱怨说“zeros()需要一个参数”,尽管wiki上说的不是这样。也许这个命令只适用于git版本。
2 个回答
SymPy 还提供了一个脚本 -- isympy -- 这是一个 IPython 的包装工具,可以执行一些常用的命令,包括从未来引入除法。这非常方便,而且在更新的 IPython 版本(0.11 及以上)中,它还允许自动创建符号(这点很好,因为我总是忘记怎么做);你可以用 -a 参数来运行它。
至于 Python 3,开发版本已经支持它,下一次发布也会包含这个功能;至于各个版本什么时候会打包这个功能,我就不太清楚了。
在使用 ipython -i
命令和 ipython
解释器中的 run -i
时,它们会忽略 from __future__ import division
这行代码,这行代码是在 print05.py
脚本里。
$ cat print05.py
from __future__ import division
print(1/2)
在 ipython
控制台中:
In [1]: print 1/2
0
In [2]: run -i print05.py
0.5
In [3]: division
Out[3]: _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)
In [4]: print 1/2
0
In [5]: from __future__ import division
In [6]: print 1/2
0.5
execfile
和 import
的结果是一样的:
>>> print 1/2
0
>>> execfile('print05.py')
0.5
>>> print 1/2
0
>>> from __future__ import division
>>> print 1/2
0.5
from __future__ import division
这行代码不应该影响来自不同模块的源代码,否则会导致其他模块的代码出错,因为它们并不期望这行代码的存在。
在这里,from __future__ import division
是有效的:
$ python -i print05.py
0.5
>>> print 1/2
0.5
>>> division
_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)
在这种情况下,模块的名称是 __main__
,无论是在 print05.py
里还是在提示符中。
这里,第一个 print 1/2
在 print05
模块中执行,第二个在 __main__
模块中执行,所以它也按预期工作:
$ python -im print05
0.5
>>> print 1/2
0
但这里有点问题:
$ ipython -i print05.py
0.5
In [1]: division
Out[1]: _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)
In [2]: print 1/2
0
关于 __future__
的文档中说:
如果解释器是通过 -i 选项启动的,并且传入了一个要执行的脚本名,而这个脚本包含了未来声明,那么在脚本执行后启动的交互会话中,这个声明将会生效。
所以,如果 ipython
的 -i
选项试图模拟同样的 Python 选项,那可能就是个 bug。