Evaluating a String in Sage - Utilities

Skip to content
Back to top
View this page
Edit this page

# Evaluating a String in Sage

sage.misc.sage_eval.sage_eval(source, locals=None, cmds='', preparse=True)

  Obtain a Sage object from the input string by evaluating it using Sage. This means calling eval after preparsing and with globals equal to everything included in the scope of `from sage.all import *`.).

  INPUT:

  - `source` – string or object with a `_sage_` method

  - `locals` – evaluate in namespace of `sage.all` plus the locals dictionary

  - `cmds` – string; sequence of commands to be run before source is evaluated

  - `preparse` – boolean (default: `True`); if `True`, preparse the string expression

  EXAMPLES: This example illustrates that preparsing is applied:

  Sage

      sage: eval('2^3')
      1
      sage: sage_eval('2^3')
      8

  Python

      >>> from sage.all import *
      >>> eval('2^3')
      1
      >>> sage_eval('2^3')
      8

  However, preparsing can be turned off:

  Sage

      sage: sage_eval('2^3', preparse=False)
      1

  [Python]

      >>> from sage.all import *
      >>> sage_eval('2^3', preparse=False)
      1

  Note that you can explicitly define variables and pass them as the second option:

  Sage

      sage: x = PolynomialRing(RationalField(),"x").gen()
      sage: sage_eval('x^2+1', locals={'x':x})
      x^2 + 1

  Python

      >>> from sage.all import *
      >>> x = PolynomialRing(RationalField(),"x").gen()
      >>> sage_eval('x^2+1', locals={'x':x})
      x^2 + 1

  This example illustrates that evaluation occurs in the context of `from sage.all import *`. Even though `bernoulli` has been redefined in the local scope, when calling `sage_eval()` the default value meaning of `bernoulli()` is used. Likewise for `QQ` below:

  Sage

      sage: bernoulli = lambda x : x^2
      sage: bernoulli(6)
      36
      sage: eval('bernoulli(6)')
      36
      sage: sage_eval('bernoulli(6)')                                                 # needs sage.libs.flint
      1/42

  [Python]

      >>> from sage.all import *
      >>> bernoulli = lambda x : x**Integer(2)
      >>> bernoulli(Integer(6))
      36
      >>> eval('bernoulli(6)')
      36
      >>> sage_eval('bernoulli(6)')                                                 # needs sage.libs.flint
      1/42

  Sage

      sage: QQ = lambda x : x^2
      sage: QQ(2)
      4
      sage: sage_eval('QQ(2)')
      2
      sage: parent(sage_eval('QQ(2)'))
      Rational Field

  Python

      >>> from sage.all import *
      >>> QQ = lambda x : x**Integer(2)
      >>> QQ(Integer(2))
      4
      >>> sage_eval('QQ(2)')
      2
      >>> parent(sage_eval('QQ(2)'))
      Rational Field

  This example illustrates setting a variable for use in evaluation:

  Sage

      sage: x = 5
      sage: eval('4//3 + x', {'x': 25})
      26
      sage: sage_eval('4/3 + x',  locals={'x': 25})
      79/3

  [Python]

      >>> from sage.all import *
      >>> x = Integer(5)
      >>> eval('4//3 + x', {'x': Integer(25)})
      26
      >>> sage_eval('4/3 + x',  locals={'x': Integer(25)})
      79/3

  You can also specify a sequence of commands to be run before the expression is evaluated:

  Sage

      sage: sage_eval('p', cmds='K.<x> = QQ[]\np = x^2 + 1')
      x^2 + 1

  Python

      >>> from sage.all import *
      >>> sage_eval('p', cmds='K.<x> = QQ[]\np = x^2 + 1')
      x^2 + 1

  If you give commands to execute and a dictionary of variables, then the dictionary will be modified by assignments in the commands:

  Sage

      sage: vars = {}
      sage: sage_eval('None', cmds='y = 3', locals=vars)
      sage: vars['y'], parent(vars['y'])
      (3, Integer Ring)

  [Python]

      >>> from sage.all import *
      >>> vars = {}
      >>> sage_eval('None', cmds='y = 3', locals=vars)
      >>> vars['y'], parent(vars['y'])
      (3, Integer Ring)

  You can also specify the object to evaluate as a tuple. A 2-tuple is assumed to be a pair of a command sequence and an expression; a 3-tuple is assumed to be a triple of a command sequence, an expression, and a dictionary holding local variables. (In this case, the given dictionary will not be modified by assignments in the commands.)

  Sage

      sage: sage_eval(('f(x) = x^2', 'f(3)'))                                         # needs sage.symbolic
      9
      sage: vars = {'rt2': sqrt(2.0)}
      sage: sage_eval(('rt2 += 1', 'rt2', vars))
      2.41421356237309
      sage: vars['rt2']
      1.41421356237310

  Python

      >>> from sage.all import *
      >>> sage_eval(('f(x) = x^2', 'f(3)'))                                         # needs sage.symbolic
      9
      >>> vars = {'rt2': sqrt(RealNumber('2.0'))}
      >>> sage_eval(('rt2 += 1', 'rt2', vars))
      2.41421356237309
      >>> vars['rt2']
      1.41421356237310

  This example illustrates how `sage_eval` can be useful when evaluating the output of other computer algebra systems:

  Sage

      sage: # needs sage.libs.gap
      sage: R.<x> = PolynomialRing(RationalField())
      sage: gap.eval('R:=PolynomialRing(Rationals,["x"]);')
      'Rationals[x]'
      sage: ff = gap.eval('x:=IndeterminatesOfPolynomialRing(R);; f:=x^2+1;'); ff
      'x^2+1'
      sage: sage_eval(ff, locals={'x':x})
      x^2 + 1
      sage: eval(ff)
      Traceback (most recent call last):
      ...
      RuntimeError: Use ** for exponentiation, not '^', which means xor
      in Python, and has the wrong precedence.

  [Python]

      >>> from sage.all import *
      >>> # needs sage.libs.gap
      >>> R = PolynomialRing(RationalField(), names=('x',)); (x,) = R._first_ngens(1)
      >>> gap.eval('R:=PolynomialRing(Rationals,["x"]);')
      'Rationals[x]'
      >>> ff = gap.eval('x:=IndeterminatesOfPolynomialRing(R);; f:=x^2+1;'); ff
      'x^2+1'
      >>> sage_eval(ff, locals={'x':x})
      x^2 + 1
      >>> eval(ff)
      Traceback (most recent call last):
      ...
      RuntimeError: Use ** for exponentiation, not '^', which means xor
      in Python, and has the wrong precedence.

  Here you can see that `eval()` simply will not work but `sage_eval()` will.

sage.misc.sage_eval.sageobj(x, vars=None)

  Return a native Sage object associated to `x`, if possible and implemented.

  If the object has a `_sage_` method it is called and the value is returned. Otherwise, `str()` is called on the object, and all preparsing is applied and the resulting expression is evaluated in the context of `from sage.all import *`. To evaluate the expression with certain variables set, use the `vars` argument, which should be a dictionary.

  EXAMPLES:

  Sage

      sage: type(sageobj(gp('34/56')))                                                # needs sage.libs.pari
      <class 'sage.rings.rational.Rational'>

      sage: n = 5/2
      sage: sageobj(n) is n
      True
      sage: k = sageobj('Z(8^3/1)', {'Z':ZZ}); k
      512
      sage: type(k)
      <class 'sage.rings.integer.Integer'>

  Python

      >>> from sage.all import *
      >>> type(sageobj(gp('34/56')))                                                # needs sage.libs.pari
      <class 'sage.rings.rational.Rational'>

      >>> n = Integer(5)/Integer(2)
      >>> sageobj(n) is n
      True
      >>> k = sageobj('Z(8^3/1)', {'Z':ZZ}); k
      512
      >>> type(k)
      <class 'sage.rings.integer.Integer'>

  This illustrates interfaces:

  Sage

      sage: # needs sage.libs.pari
      sage: f = gp('2/3')
      sage: type(f)
      <class 'sage.interfaces.gp.GpElement'>
      sage: f._sage_()
      2/3
      sage: type(f._sage_())
      <class 'sage.rings.rational.Rational'>

      sage: # needs sage.libs.gap
      sage: a = gap(939393/2433)
      sage: a._sage_()
      313131/811
      sage: type(a._sage_())
      <class 'sage.rings.rational.Rational'>

  [Python]

      >>> from sage.all import *
      >>> # needs sage.libs.pari
      >>> f = gp('2/3')
      >>> type(f)
      <class 'sage.interfaces.gp.GpElement'>
      >>> f._sage_()
      2/3
      >>> type(f._sage_())
      <class 'sage.rings.rational.Rational'>

      >>> # needs sage.libs.gap
      >>> a = gap(Integer(939393)/Integer(2433))
      >>> a._sage_()
      313131/811
      >>> type(a._sage_())
      <class 'sage.rings.rational.Rational'>