Convert mathematica math expression form to python math expression?

FortranForm gets you close. ( Fortran and Python use the same syntax for most things )

    pw = PageWidth /. Options[$Output];
    SetOptions[$Output, PageWidth ->Infinity];
    FortranForm[ expression  /. E^x_ :> exp[x] ]
    SetOptions[$Output, PageWidth -> pw];

(1.*(43.013537902165325 + 43.013537902165346*exp(0.003288590604026849*t))**2)/(3700.328885722024 + 5.4569682106375694e-12*exp(0.003288590604026849*t) + 3700.328885722026*exp(0.006577181208053698*t))

note we need to set pagewidth because you sure don't want Fortran continuation marks. The E^x_ replacement puts the exponential into python form, you will need to do similar with other functions.

One thing to be careful about, if you have integer rationals in your mathematica expression they give you integer arithmetic in python, which is not likely what you want. In that case you can apply N to the whole works, although that can have other issues.

Edit, refinement:

 FortranForm[ expression  //. {1. y_ -> y, E^x_ -> exp[x]  }]

gets rid of the superfluous 1. multipliers.


Maybe you could convert expressions from mathematica to latex then use Latex Lambda to get back the python function. Latex Lambda converts latex math notation to lambda functions in Python. So you would input mathematica converted latex expressions and get back the python function.

Example:

Input

     \prod_{i=1}^{n}\frac{\arcsin{\alpha}*\sin{\beta}}{\sqrt{\alpha*\beta}}

Output

{
    "func":"lambda n,ß,α: np.prod([(np.arcsin(α)*np.sin(ß))/(np.sqrt(α*ß)) for i in range(int(1),int(n)+1)])",
    "params":["n", "ß", "α"]
}

Evaluation

>>> import numpy as np
>>> func = lambda n,ß,α: np.prod([(np.arcsin(α)*np.sin(ß))/(np.sqrt(α*ß)) for i in range(int(1),int(n)+1))])
>>> func(4,1,1)
3.05236236307

Using Robert Jacobson's FoxySheep parser, the command-line utility foxy-sheep has a crude translation to Python. See https://pypi.org/project/FoxySheep/ . (And https://github.com/rljacobson/FoxySheep .)

Conversion to Python is done via transforming “InputForm” input to an “FullForm” parse tree, and then that is converted to a Python AST. Finally a Python module is used to dump the Python AST to text.

Why do we go through this more complicated process for translating one string to another?

By keeping the structure as an AST, we can contemplate more powerful transformations and make use of routines that exist for working with Python AST’s.

For example, translating {1,2,3} + 2 into Python, while not handled now, can be done by looking at the types of the operands of plus, and noticing one is a scalar while the other is a list.

Edit:

After writing this, I tried the program on the example above and found I had to extend the code to handle symbols like E and numeric literals with a number-literal exponent.

However after doing that I was able to get this to parse:

$ foxy-sheep -o python -e '(1.*(43.013537902165325 +
43.013537902165346*E^(0.003288590604026849*t))^2)/ 
(3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 
3700.328885722026*E^(0.006577181208053698*t))'
(
 decimal.Decimal(1.0) * (
 decimal.Decimal(43.013537902165325) + 
 decimal.Decimal(43.013537902165346) * math.e ** (
 decimal.Decimal(0.003288590604026849) * t)) ** 2 / (
 decimal.Decimal(3700.328885722024) + 
 decimal.Decimal(5.456968210637569) * 10 ** 12 * math.e ** (
 decimal.Decimal(0.003288590604026849) * t) + 
 decimal.Decimal(3700.328885722026) * math.e **decimal.Decimal(0.006577181208053698) * t))

Above, we output using math.e because the output is for Python. Had the output been either the numpy or sympy variants, constants from those modules would have been used instead.

To see a parse of this expression run:

foxy-sheep -t full -e '(1.*(43.013537902165325 + 43.013537902165346*E^(0.003288590604026849*t))^2)/ (3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 3700.328885722026*E^(0.006577181208053698*t))'

<prog:Prog> [1]
  <expr:Divide> [3]
    0. <expr:Parentheses> [3]
      '('

      1. <expr:Times> [3]
        0. <expr:Number> [1]
          <numberLiteral:NumberBaseTen> [1]
            '1.'

        1. '*'

        2. <expr:Power> [3]
          0. <expr:Parentheses> [3]
            '('

            1. <expr:PlusOp> [3]
              0. <expr:Number> [1]
                <numberLiteral:NumberBaseTen> [1]
                  '43.013537902165325'

              1. '+'

              2. <expr:Times> [3]
...       

Lastly, I should explain that I was tempted to add a translation from Pi to math.pi when adding the translation of E to math.e. (This has since been done).

Right now what's more important is getting the overall framework right than filling out the hundreds of specifics. That said, for those who use and have a specific function that's missing, just open an github issue.