在我的程序中使用了 "from __future__ import division",但它没有被加载进我的程序中。

19
我在Python 2中编写了下面的程序来计算牛顿迭代法来解决我的数学问题集,它完美地工作,但出于我不知道的原因,当我最初使用%run -i NewtonsMethodMultivariate.py在ipython加载它时,Python 3的除法没有被导入。我知道这是因为在加载Python程序后,输入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 Jacobians,并且在我的问题集中只需要处理2x2矩阵。此外,我正在使用切片操作2x2的零矩阵,而不是使用命令zeros(2,1),因为安装在我的机器上的SymPy 0.7.1会抱怨“zeros()需要一个参数”,尽管wiki中显示的是相反的情况。也许这个命令只适用于git版本。(感谢eryksun纠正我的符号表示,这解决了与零函数的问题。)


这是 zeros((2,1));参数可以是标量或元组。你是否在导入后立即使用 print 1/2 测试了除法? - Eryk Sun
出于好奇,如果您在程序末尾添加 print division,会发生什么?它是否会打印出类似这样的内容:_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)?如果是这样,那么从ipython命令行中执行相同的打印语句会得到什么结果?请注意,“ipython from future import division”有数万个谷歌搜索结果。看来您不是第一个注意到这个问题的人。 :-) - Kirk Strauser
@eryksun 感谢您纠正我使用 zeros 命令的方式; 我已经更新了我的程序。如果我打开 ipython,运行 from __future__ import division,然后 print 1/2,结果是0.5,与预期相符。但是如果我在打开 ipython 并运行 %run -i NewtonsMethodMultivariate.py 后,再运行 print 1/2,则得到了0。明显地,在我的程序中导入了 Python 3 的除法,所以我不知道出了什么问题。 - Sara Fauzia
@KirkStrauser 我已经谷歌过了,但是使用我引用的除法导入行似乎没有效果,为什么呢?从iPython命令行中,当我在程序的最后一行添加print division时,我得到了你所说的结果。从命令行中也是如此。 - Sara Fauzia
为什么要硬编码你的 h 函数或考虑转移到 py3,而不是输入 x**(3/4.)x**0.75 - John Machin
@JohnMachin 我只是想避免小数。此外,我的矩阵a中有分数(硬编码的h无法解决),在第一次迭代中,矩阵a中的分数条目给出了更好的解决方案。 - Sara Fauzia
2个回答

12

ipython解释器中,无论是ipython -i命令还是run -i命令,都会忽略print05.py脚本中的from __future__ import division语句。

$ 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选项启动解释器,传递要执行的脚本名称,并且脚本包含future语句,则在执行脚本后启动的交互式会话中将生效。

因此,如果ipython-i选项试图模拟相同的Python选项,则可能是一个bug。


非常感谢您的解释。很不幸,因为我在ipython命令行上输入了我的函数“h”,它具有分数指数项,但我想如果我不想手动导入未来除法,我必须将“h”硬编码到程序中。 - Sara Fauzia
@Sara Fauzia: 如果你在 ..import division 之前定义了 h() 函数,它将使用 整数 除法。你可以使用 edit you_module.pyipython 控制台中添加函数。 - jfs
@J.F. Sebastian,正如您所指出的那样,使用Python进行交互确实可以正常工作,我刚刚测试过了。这是一个错误吗?在IPython中会发生什么? - Sara Fauzia
@Sara Fauzia:我已经更新了答案,并引用了__future__文档中的一句话。 - jfs
@Sara Fauzia:即使这种行为是ipython预期的,但至少ipython关于-i选项的文档应该提到它不符合python -i的期望,因此值得提交一个错误报告。顺便说一句,jython(Java实现的Python)按预期工作并打印出0.5。但是ipythonpypy(使用RPython实现的Python)不同,也会打印出0 - jfs
显示剩余3条评论

0
SymPy还提供了一个脚本isympy,它是IPython的包装器,可以执行一些常见命令,包括从future导入division。这非常方便,在较新的IPython版本(0.11+)中,它还允许自动构建符号(这很好,因为我总是忘记);使用-a参数运行它。
至于Python 3,在开发版本中已经支持,并且下一个发布版本也将支持;关于发行版何时打包它,我不清楚。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接