Не удается преобразовать выражение в число с плавающей запятой

Я пытаюсь изучить все тонкости символических манипуляций в python (я новичок).

У меня есть следующий базовый код, и вывод дает мне ошибку, говорящую мне, что он «не может преобразовать выражение в число с плавающей запятой».

Что не так с этим кодом:

from sympy import *
from math import *

def h(x):
    return log(0.75392 * x)

x = symbols('x')
hprime = h(x).diff(x)

print(hprime)

person Community    schedule 30.05.2017    source источник
comment
просто удалите from math import *   -  person Azat Ibrakov    schedule 30.05.2017
comment
@user46944 user46944 Я считаю, что проблема вызвана тем, что math добавляется после sympy. Просто поменяйте местами первые две строки, и все готово. Прочитайте это для получения дополнительной информации.   -  person Adeel Ahmad    schedule 30.05.2017


Ответы (2)


Это классический пример того, что говорится в PEP-8 о импорт подстановочных знаков:

Импорта с подстановочными знаками ( from <module> import * ) следует избегать, поскольку они делают неясным, какие имена присутствуют в пространстве имен, что сбивает с толку как читателей, так и многие автоматизированные инструменты.

Проблема в том, что вам нужно работать с sympy.log, но с использованием функции math.log, которая работает с объектами float, а не Symbol.

Когда вы пишете

from sympy import *

вы импортируете в пространство имен вашего модуля все, что пакет sympy предоставляет на верхнем уровне (и есть много вещей, большая часть которых вам вообще не нужна), включая класс sympy.log.

После следующего утверждения

from math import *

вы импортируете все в модуль math, включая math.log, который перезаписывает ранее импортированный класс sympy.log.

Учитывая это, ваш пример может быть написан как

import sympy


def h(x):
    return sympy.log(0.485022 * x)


x = sympy.symbols('x')
h_x = h(x)
hprime = h_x.diff(x)

print(hprime)

дает нам

1.0/x

П. С.: Я удалил импорт math, так как он не используется в данном примере.

person Azat Ibrakov    schedule 30.05.2017
comment
Да, это так. Это похоже на переопределение функции. Последнее определение останется. - person laolux; 30.05.2017
comment
Я хотел бы, чтобы это было так просто, но это не так. Я не заглядывал в пакеты, но представьте, что math определяет функцию ln, а sympy — нет. Затем вы делаете import math as * и import sympy as *. Теперь, если вы вызовете log, тогда python будет использовать sympy.log, так как он был вызван последним. Но если вы вызовете ln, то он будет использовать math.ln, потому что sympy.ln нет. Видите ли, импорт как * очень быстро сбивает с толку. - person laolux; 30.05.2017
comment
@user46944: Система импорта Python поначалу сложна, но вы к ней привыкнете, а потом поймете ее крутость, я думаю - person Azat Ibrakov; 30.05.2017
comment
@user46944: документы — хорошее место для начала. - person Azat Ibrakov; 30.05.2017

Проблема здесь в том, что и пакет sympy, и пакет math определяют функцию с именем log.

Импортируя их как from sympy import *, а затем from math import *, вместо sympy.log используется math.log.

Лучше всегда использовать import sympy, а затем вызывать свои функции sympy.log или (если такой же ленивый, как я) делать import sympy as sym, а затем sym.log. Не забудьте сделать это и с математическим пакетом. Этот метод избавит вас от многих хлопот в будущем и сделает ваш код более понятным для других.

person laolux    schedule 30.05.2017
comment
Да, ты можешь. На самом деле вы можете сделать import sympy as np и import numpy as sym. Это действительный код Python, и интерпретатор Python не будет жаловаться, но он наверняка запутает любого, кто читает ваш код (включая вас в какой-то момент). Так что можете, но мой совет НЕ ДЕЛАЙТЕ! - person laolux; 30.05.2017