4

I'm trying to learn the ins and outs of symbolic manipulation in python (I'm a beginner).

I have the following basic code, and the output is giving me an error telling me that it "can't convert expression to float".

What's wrong with this code:

from sympy import *
from math import *

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

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

print(hprime)
Adeel Ahmad
  • 1,033
  • 1
  • 11
  • 24
  • just remove `from math import *` – Azat Ibrakov May 30 '17 at 13:44
  • 1
    @user46944 I believe the problem is being caused because `math` is being included after `sympy`. Just swap the first two lines and you're good to go. Read [this](https://stackoverflow.com/questions/4092395/python-import-precedence-packages-or-modules) for more info. – Adeel Ahmad May 30 '17 at 13:48

2 Answers2

9

This is a classic example of what is said in PEP-8 about wildcard imports:

Wildcard imports ( from <module> import * ) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.

The problem is that you need to work with sympy.log class, but using math.log function instead which works on float objects, not Symbol objects.

When you write

from sympy import *

you are importing in your module namespace everything that sympy package providing at the top level (and there are a lot of stuff, much of that you don't need at all), including sympy.log class.

After next statement

from math import *

you are importing everything in math module, including math.log, which overwrites previously imported sympy.log class.

Considering this your example may be written like

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)

gives us

1.0/x

P. S.: I've removed math import since it is not used in given example.

Azat Ibrakov
  • 9,998
  • 9
  • 38
  • 50
  • 1
    Yes, it does. It is like redefining a function. The last definition will stick. – laolux May 30 '17 at 13:57
  • I wish it was that easy, but it is not. I have not looked into the packages, but imagine that `math` defines a function `ln` whereas `sympy` does not. Then you do `import math as *` and `import sympy as *`. Now if you call `log`, then python will use `sympy.log` since it was called last. But if you call `ln`, then it will use `math.ln`, because there is no `sympy.ln`. You see, importing as * gets confusing really fast. – laolux May 30 '17 at 14:07
  • 1
    @user46944: **Python** import system is a hard thing at first, but you will get used to it and then understand its awesomeness, i guess – Azat Ibrakov May 30 '17 at 14:14
  • 1
    @user46944: [docs](https://docs.python.org/3/reference/import.html) is a good place to start – Azat Ibrakov May 30 '17 at 14:16
3

The problem here is that both the sympy and the math package define a function called log.

Importing them as from sympy import * and then from math import * overrides the sympy.log with math.log.

Better always use import sympy and then call your functions sympy.log or (if as lazy as me) do import sympy as sym and then sym.log. Be sure to do so with the math package as well. This method will save you a lot of hassle in the future and makes your code easier to understand for others.

laolux
  • 1,445
  • 1
  • 17
  • 28
  • 1
    Yes, you can. You can actually do `import sympy as np` and `import numpy as sym`. It's valid python code and the python interpreter will not complain, but it will for sure confuse anyone reading your code (including yourself at some point). So you can, but my advice is DON'T! – laolux May 30 '17 at 14:04