Using eval with substitutions

Anthra Norell anthra.norell at tiscalinet.ch
Sat Sep 2 10:48:34 CEST 2006


----- Original Message -----
From: "Carl Banks" <pavlovevidence at gmail.com>
Newsgroups: comp.lang.python
To: <python-list at python.org>
Sent: Saturday, September 02, 2006 6:33 AM
Subject: Re: Using eval with substitutions


> abhishek at ocf.berkeley.edu wrote:
> > >>> a,b=3,4
> > >>> x="a+b"
...
 > Careful.  Here be dragons.
...
> However, this is just a big potentially dangerous hack.  It's probably
...

> Carl Banks

-----------------------

Dragons indeed!
      To wit, I did get carried away a little with my suggestions and derived a class Formlua_Expander from SE. A few hours later it
worked just beautifully:

>>> FE = FORMEX.Formula_Expander ()
>>> FE.define ('l=102.8')
>>> FE.define ('d=8.5')
>>> FE.define ('pi=3.14159')
>>> FE.define ('r=d/2')
>>> FE.define ('section=r*r*pi')
>>> FE.define ('pipe_volume=l*section')
>>> FE ('pipe_volume')
5833.3828517499996
>>> FE.expand ('pipe_volume')
'((102.8)*(((8.5)/2)*((8.5)/2)*(3.14159)))'

The expansion cascade:

Data Chain
----------------------------------------------------------------------------------
  pipe_volume
0 --------------------------------------------------------------------------------
  (l*section)
1 --------------------------------------------------------------------------------
  (l*(r*r*pi))
2 --------------------------------------------------------------------------------
  (l*((d/2)*(d/2)*pi))
3 --------------------------------------------------------------------------------
  ((102.8)*(((8.5)/2)*((8.5)/2)*(3.14159)))
----------------------------------------------------------------------------------

Wonderful! Some more:

>>> FE.define ('m_per_foot=0.3048')
>>> FE.define ('pipe_volume_metric=pipe_volume*m_per_foot')
>>> FE ('pipe_volume_metric')

Traceback (most recent call last):
  File "<pyshell#199>", line 1, in -toplevel-
    FE ('pipe_volume_metric')
  File "c:\i\sony\fre\src\python\FORMEX.py", line 175, in __call__
    try: return eval (expression)
  File "<string>", line 1
    (((102.8)*(((8.5)/2)*((8.5)/2)*(3.14159)))*m_pe((8.5)/2)_foot(102.8)e)
                                                                ^
Oops!

>>> FE.show (1)
...
(1st pass) ...
    1: |pipe_volume_metric|->|(pipe_volume*m_per_foot)|
(2nd pass) ...
    1: |pipe_volume|->|(l*section)|
(3rd pass) ...
    1: |section|->|(r*r*pi)|
(4th pass) ...
    1: |r|->|(d/2)|
(5th pass) ...
    1: |d|->|(8.5)|
    2: |l|->|(102.8)|
    3: |m_per_foot|->|(0.3048)|
    4: |pi|->|(3.14159)|

Data Chain
----------------------------------------------------------------------------------
  pipe_volume_metric
0 --------------------------------------------------------------------------------
  (pipe_volume*m_per_foot)
1 --------------------------------------------------------------------------------
  ((l*section)*m_per_foot)
2 --------------------------------------------------------------------------------
  ((l*(r*r*pi))*m_per_foot)
3 --------------------------------------------------------------------------------
  ((l*((d/2)*(d/2)*pi))*m_pe(d/2)_foot)
4 --------------------------------------------------------------------------------
  (((102.8)*(((8.5)/2)*((8.5)/2)*(3.14159)))*m_pe((8.5)/2)_foot(102.8)e)
----------------------------------------------------------------------------------

An unwanted substitution occurs in pass 4 when the 'r' in 'm_per_foot' is replaced
by the substitution meant for 'r' (radius).

Conclusion: Forget it! - Forget this approach anyway. There are probably formula parsers out there that are more intelligent than
this hack.

Frederic

(Learning by making mistakes is faster than by avoiding mistakes and if it's fun on top of it all the better.)





More information about the Python-list mailing list