Abstract base class for Sage objects#

class sage.structure.sage_object.SageObject#

Bases: object

Base class for all (user-visible) objects in Sage

Every object that can end up being returned to the user should inherit from SageObject.


Return an ASCII art representation.

To implement multi-line ASCII art output in a derived class you must override this method. Unlike _repr_(), which is sometimes used for the hash key, the output of _ascii_art_() may depend on settings and is allowed to change during runtime.


An AsciiArt object, see sage.typeset.ascii_art for details.


You can use the ascii_art() function to get the ASCII art representation of any object in Sage:

sage: result = ascii_art(integral(exp(x+x^2)/(x+1), x))                     # needs sage.symbolic
sage: result                                                                # needs sage.symbolic
 |   2
 |  x  + x
 | e
 | ------- dx
 |  x + 1

Alternatively, you can use the %display ascii_art/simple magic to switch all output to ASCII art and back:

sage: # needs sage.combinat
sage: from sage.repl.interpreter import get_test_shell
sage: shell = get_test_shell()
sage: shell.run_cell('tab = StandardTableaux(3)[2]; tab')
[[1, 2], [3]]
sage: shell.run_cell('%display ascii_art')
sage: shell.run_cell('tab')
1  2
sage: shell.run_cell('Tableaux.options(ascii_art="table", convention="French")')
sage: shell.run_cell('tab')
| 3 |
| 1 | 2 |
sage: shell.run_cell('%display plain')
sage: shell.run_cell('Tableaux.options._reset()')
sage: shell.quit()

Return a hashable key which identifies this objects for caching. The output must be hashable itself, or a tuple of objects which are hashable or define a _cache_key.

This method will only be called if the object itself is not hashable.

Some immutable objects (such as \(p\)-adic numbers) cannot implement a reasonable hash function because their == operator has been modified to return True for objects which might behave differently in some computations:

sage: # needs sage.rings.padics
sage: K.<a> = Qq(9)
sage: b = a + O(3)
sage: c = a + 3
sage: b
a + O(3)
sage: c
a + 3 + O(3^20)
sage: b == c
sage: b == a
sage: c == a

If such objects defined a non-trivial hash function, this would break caching in many places. However, such objects should still be usable in caches. This can be achieved by defining an appropriate _cache_key:

sage: # needs sage.rings.padics
sage: hash(b)
Traceback (most recent call last):
TypeError: unhashable type: 'sage.rings.padics.qadic_flint_CR.qAdicCappedRelativeElement'
sage: @cached_method
....: def f(x): return x==a
sage: f(b)
sage: f(c)  # if b and c were hashable, this would return True
sage: b._cache_key()
(..., ((0, 1),), 0, 1)
sage: c._cache_key()
(..., ((0, 1), (1,)), 0, 20)

An implementation must make sure that for elements a and b, if a != b, then also a._cache_key() != b._cache_key(). In practice this means that the _cache_key should always include the parent as its first argument:

sage: S.<a> = Qq(4)                                                         # needs sage.rings.padics
sage: d = a + O(2)                                                          # needs sage.rings.padics
sage: b._cache_key() == d._cache_key()  # this would be True if the parents were not included               # needs sage.rings.padics
dump(filename, compress=True)#

Same as self.save(filename, compress)


Dump self to a string s, which can later be reconstituted as self using loads(s).

There is an optional boolean argument compress which defaults to True.


sage: from sage.misc.persist import comp
sage: O = SageObject()
sage: p_comp = O.dumps()
sage: p_uncomp = O.dumps(compress=False)
sage: comp.decompress(p_comp) == p_uncomp
sage: import pickletools
sage: pickletools.dis(p_uncomp)
    0: \x80 PROTO      2
    2: c    GLOBAL     'sage.structure.sage_object SageObject'
   41: q    BINPUT     ...
   43: )    EMPTY_TUPLE
   44: \x81 NEWOBJ
   45: q    BINPUT     ...
   47: .    STOP
highest protocol among opcodes = 2

Return the custom name of this object, or None if it is not renamed.


sage: P.<x> = QQ[]
sage: P.get_custom_name() is None
sage: P.rename('A polynomial ring')
sage: P.get_custom_name()
'A polynomial ring'
sage: P.reset_name()
sage: P.get_custom_name() is None

Return the type of self to support the coercion framework.


sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t                            # needs sage.symbolic
log(sqrt(2) + 1) + log(sqrt(2) - 1)
sage: u = t.maxima_methods()                                                # needs sage.symbolic
sage: u.parent()                                                            # needs sage.symbolic
<class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>

Change self so it prints as x, where x is a string.

If x is None, the existing custom name is removed.


This is only supported for Python classes that derive from SageObject.


sage: x = PolynomialRing(QQ, 'x', sparse=True).gen()
sage: g = x^3 + x - 5
sage: g
x^3 + x - 5
sage: g.rename('a polynomial')
sage: g
a polynomial
sage: g + x
x^3 + 2*x - 5
sage: h = g^100
sage: str(h)[:20]
'x^300 + 100*x^298 - '
sage: h.rename('x^300 + ...')
sage: h
x^300 + ...
sage: g.rename(None)
sage: g
x^3 + x - 5

Real numbers are not Python classes, so rename is not supported:

sage: a = 3.14
sage: type(a)                                                               # needs sage.rings.real_mpfr
<... 'sage.rings.real_mpfr.RealLiteral'>
sage: a.rename('pi')                                                        # needs sage.rings.real_mpfr
Traceback (most recent call last):
NotImplementedError: object does not support renaming: 3.14000000000000


The reason C-extension types are not supported by default is if they were then every single one would have to carry around an extra attribute, which would be slower and waste a lot of memory.

To support them for a specific class, add a cdef public _SageObject__custom_name attribute.


Remove the custom name of an object.


sage: P.<x> = QQ[]
sage: P
Univariate Polynomial Ring in x over Rational Field
sage: P.rename('A polynomial ring')
sage: P
A polynomial ring
sage: P.reset_name()
sage: P
Univariate Polynomial Ring in x over Rational Field
save(filename=None, compress=True)#

Save self to the given filename.


sage: # needs sage.symbolic
sage: x = SR.var("x")
sage: f = x^3 + 5
sage: from tempfile import NamedTemporaryFile
sage: with NamedTemporaryFile(suffix=".sobj") as t:
....:     f.save(t.name)
....:     load(t.name)
x^3 + 5