在我的程序中使用"from __future__ import division",但未能加载

19 投票
2 回答
40951 浏览
提问于 2025-04-17 07:11

我写了一个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的零矩阵时,选择了切片,而不是使用zeros(2,1)这个命令,因为我机器上安装的SymPy 0.7.1抱怨说“zeros()需要一个参数”,尽管wiki上说的不是这样。也许这个命令只适用于git版本。(感谢eryksun纠正了我的符号,这解决了zeros函数的问题。)

2 个回答

0

SymPy 还提供了一个脚本 -- isympy -- 这是一个 IPython 的包装工具,可以执行一些常用的命令,包括从未来引入除法。这非常方便,而且在更新的 IPython 版本(0.11 及以上)中,它还允许自动创建符号(这点很好,因为我总是忘记怎么做);你可以用 -a 参数来运行它。

至于 Python 3,开发版本已经支持它,下一次发布也会包含这个功能;至于各个版本什么时候会打包这个功能,我就不太清楚了。

12

在使用 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

execfileimport 的结果是一样的:

>>> 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/2print05 模块中执行,第二个在 __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。

撰写回答