Evaluating a String in Sage¶
- sage.misc.sage_eval.sage_eval(source, locals=None, cmds='', preparse=True)[source]¶
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_
methodlocals
– evaluate in namespace ofsage.all
plus the locals dictionarycmds
– string; sequence of commands to be run before source is evaluatedpreparse
– boolean (default:True
); ifTrue
, preparse the string expression
EXAMPLES: This example illustrates that preparsing is applied:
sage: eval('2^3') 1 sage: sage_eval('2^3') 8
>>> from sage.all import * >>> eval('2^3') 1 >>> sage_eval('2^3') 8
However, preparsing can be turned off:
sage: sage_eval('2^3', preparse=False) 1
>>> 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: x = PolynomialRing(RationalField(),"x").gen() sage: sage_eval('x^2+1', locals={'x':x}) x^2 + 1
>>> 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 thoughbernoulli
has been redefined in the local scope, when callingsage_eval()
the default value meaning ofbernoulli()
is used. Likewise forQQ
below: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
>>> 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: QQ = lambda x : x^2 sage: QQ(2) 4 sage: sage_eval('QQ(2)') 2 sage: parent(sage_eval('QQ(2)')) Rational Field
>>> 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: x = 5 sage: eval('4//3 + x', {'x': 25}) 26 sage: sage_eval('4/3 + x', locals={'x': 25}) 79/3
>>> 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_eval('p', cmds='K.<x> = QQ[]\np = x^2 + 1') x^2 + 1
>>> 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: vars = {} sage: sage_eval('None', cmds='y = 3', locals=vars) sage: vars['y'], parent(vars['y']) (3, Integer Ring)
>>> 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_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
>>> 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: # 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.
>>> 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 butsage_eval()
will.
- sage.misc.sage_eval.sageobj(x, vars=None)[source]¶
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 offrom sage.all import *
. To evaluate the expression with certain variables set, use thevars
argument, which should be a dictionary.EXAMPLES:
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'>
>>> 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: # 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'>
>>> 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'>