В моей программе используется раздел импорта from __future__, но он не загружается вместе с моей программой

Я написал следующую программу на Python 2 для выполнения вычислений методом Ньютона для моего набора математических задач, и хотя она работает отлично, по неизвестным мне причинам, когда я первоначально загружаю ее в ipython с %run -i NewtonsMethodMultivariate.py, деление 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 включает SymPy только для Python 2. Спасибо за помощь, которую может предоставить любой.

Кроме того, если кому-то интересно, я еще не обобщил этот сценарий для nxn якобианцев, и мне пришлось иметь дело только с 2x2 в моем наборе задач. Кроме того, я нарезаю нулевую матрицу 2x2 вместо использования команды zeros(2,1), потому что SymPy 0.7.1, установленная на моем компьютере, жалуется, что "zeros() принимает ровно один аргумент", хотя wiki предполагает обратное. Возможно, эта команда предназначена только для версии git. (Спасибо eryksun за исправление моей записи, что устранило проблему с функцией нулей.)


person Sara Fauzia    schedule 28.11.2011    source источник
comment
Это zeros((2,1)); аргумент является либо скаляром, либо кортежем. Вы тестировали деление сразу после импорта с помощью print 1/2?   -  person Eryk Sun    schedule 28.11.2011
comment
Из любопытства, что произойдет, если вы добавите print division в конец своей программы? Он печатает что-то вроде: _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)? И если да, то что тот же оператор печати дает вам из командной строки ipython? Обратите внимание, что есть несколько десятков тысяч результатов Google для ipython из будущего отдела импорта. Кажется, вы не первый, кто это заметил. :-)   -  person Kirk Strauser    schedule 28.11.2011
comment
@eryksun Спасибо, что поправили меня в использовании команды нулей; Я обновил свою программу. Итак, если я открою ipython, запущу from __future__ import division, а затем print 1/2, результат будет 0,5, как и ожидалось. Но если я вместо этого, открыв ipython и запустив %run -i NewtonsMethodMultivariate.py, а затем print 1/2, я получаю 0. Строка для импорта подразделения Python 3 явно есть в моей программе, поэтому я не знаю, что случилось.   -  person Sara Fauzia    schedule 28.11.2011
comment
@KirkStrauser Я погуглил это, но исправление состоит в том, чтобы использовать строку импорта для деления, которую я процитировал выше, но почему это не дает эффекта? Из командной строки iPython я получаю именно то, что вы сказали после добавления print division в последнюю строку моей программы. Из командной строки я также получаю то же самое.   -  person Sara Fauzia    schedule 28.11.2011
comment
Почему вы жестко кодируете свою функцию h или рассматриваете возможность перехода на py3 вместо ввода x**(3/4.) или x**0.75 ?   -  person John Machin    schedule 28.11.2011
comment
@JohnMachin Я просто хотел избежать десятичных знаков. Кроме того, в моей матрице a были дроби (которые жесткое кодирование h не исправило бы), и в первой итерации дроби в элементах a дали лучшее решение.   -  person Sara Fauzia    schedule 28.11.2011


Ответы (2)


И команда ipython -i, и run -i в интерпретаторе ipython игнорируют 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.

person jfs    schedule 28.11.2011
comment
Большое спасибо за объяснение. К сожалению, я ввел свою функцию h в командную строку ipython, и в ней есть термины с дробными показателями, но я думаю, что мне придется жестко запрограммировать h в программе, если я не хочу импортировать будущее деление вручную. - person Sara Fauzia; 28.11.2011
comment
@Sara Fauzia: если вы определили функцию h() до ..import division, то она будет использовать целочисленное деление. Вы можете использовать edit you_module.py для добавления функций из консоли ipython. - person jfs; 28.11.2011
comment
@Дж.Ф. Себастьян. Итак, интерактивное использование python, как вы указали, действительно работает правильно, как я только что проверил. Это ошибка, что происходит с ipython? - person Sara Fauzia; 28.11.2011
comment
@Sara Fauzia: есть симпи-профиль что импортирует будущее деление. - person Eryk Sun; 28.11.2011
comment
@eryksun Но профиль по умолчанию импортирует все, и я думал, что в отдельной программе этого не делают. (Поправьте меня, если я ошибаюсь, так как я новичок.) - person Sara Fauzia; 28.11.2011
comment
@Sara Fauzia: я обновил ответ цитатой из документации __future__. - person jfs; 28.11.2011
comment
@J.F.Sebastian Из документации iPython 0.11: IPython предназначен для замены стандартного интерактивного интерпретатора. Таким образом, любой допустимый код python должен нормально выполняться под IPython (случаи, когда это не так, следует сообщать об ошибках). Итак, если я не понял неправильно, я должен подать отчет об ошибке. - person Sara Fauzia; 28.11.2011
comment
@Sara Fauzia: Даже если такое поведение ожидается для ipython, то по крайней мере в документации ipython для варианта -i должно быть указано, что оно не соответствует ожиданиям python -i, поэтому стоит подать отчет об ошибке. Кстати, jython (Python, реализованный на Java) работает, как и ожидалось, и печатает 0.5. Но ipython не совпадает с pypy (Python реализован в RPython) также печатает 0. - person jfs; 28.11.2011

SymPy также предоставляет скрипт isympy, который является оболочкой для IPython и выполняет некоторые общие команды, включая импорт разделения из будущего. Это очень удобно, и в более новых версиях IPython (0.11+) он также позволяет автоматически создавать символы (что приятно, поскольку я всегда забываю); запустите его с параметром -a.

Что касается Python 3, то он поддерживается в разрабатываемой версии и будет в следующем выпуске; когда дистрибутивы собираются его упаковать, я не знаю.

person VPeric    schedule 28.11.2011