Base class for parent objects#

CLASS HIERARCHY:

SageObject
    CategoryObject
        Parent

A simple example of registering coercions:

sage: class A_class(Parent):
....:   def __init__(self, name):
....:       Parent.__init__(self)
....:       self._populate_coercion_lists_()
....:       self.rename(name)
....:
....:   def category(self):
....:       return Sets()
....:
....:   def _element_constructor_(self, i):
....:       assert(isinstance(i, (int, Integer)))
....:       return ElementWrapper(self, i)
sage: A = A_class("A")
sage: B = A_class("B")
sage: C = A_class("C")

sage: def f(a):
....:   return B(a.value+1)
sage: class MyMorphism(Morphism):
....:   def __init__(self, domain, codomain):
....:       Morphism.__init__(self, Hom(domain, codomain))
....:
....:   def _call_(self, x):
....:       return self.codomain()(x.value)
sage: f = MyMorphism(A,B)
sage: f
    Generic morphism:
      From: A
      To:   B
sage: B.register_coercion(f)
sage: C.register_coercion(MyMorphism(B,C))
sage: A(A(1)) == A(1)
True
sage: B(A(1)) == B(1)
True
sage: C(A(1)) == C(1)
True

sage: A(B(1))
Traceback (most recent call last):
...
AssertionError

When implementing an element of a ring, one would typically provide the element class with _rmul_ and/or _lmul_ methods for the action of a base ring, and with _mul_ for the ring multiplication. However, prior to github issue #14249, it would have been necessary to additionally define a method _an_element_() for the parent. But now, the following example works:

sage: from sage.structure.element import RingElement
sage: class MyElement(RingElement):
....:      def __init__(self, parent, x, y):
....:          RingElement.__init__(self, parent)
....:      def _mul_(self, other):
....:          return self
....:      def _rmul_(self, other):
....:          return self
....:      def _lmul_(self, other):
....:          return self
sage: class MyParent(Parent):
....:      Element = MyElement

Now, we define

sage: P = MyParent(base=ZZ, category=Rings())
sage: a = P(1,2)
sage: a*a is a
True
sage: a*2 is a
True
sage: 2*a is a
True
class sage.structure.parent.EltPair#

Bases: object

short_repr()#
class sage.structure.parent.Parent#

Bases: CategoryObject

Base class for all parents.

Parents are the Sage/mathematical analogues of container objects in computer science.

INPUT:

  • base – An algebraic structure considered to be the “base” of this parent (e.g. the base field for a vector space).

  • category – a category or list/tuple of categories. The category in which this parent lies (or list or tuple thereof). Since categories support more general super-categories, this should be the most specific category possible. If category is a list or tuple, a JoinCategory is created out of them. If category is not specified, the category will be guessed (see CategoryObject), but will not be used to inherit parent’s or element’s code from this category.

  • names – Names of generators.

  • normalize – Whether to standardize the names (remove punctuation, etc)

  • facade – a parent, or tuple thereof, or True

If facade is specified, then Sets().Facade() is added to the categories of the parent. Furthermore, if facade is not True, the internal attribute _facade_for is set accordingly for use by Sets.Facade.ParentMethods.facade_for().

Internal invariants:

  • self._element_init_pass_parent == guess_pass_parent(self, self._element_constructor) Ensures that __call__() passes down the parent properly to _element_constructor(). See github issue #5979.

Todo

Eventually, category should be Sets by default.

__call__(x=0, *args, **kwds)#

This is the generic call method for all parents.

When called, it will find a map based on the Parent (or type) of x. If a coercion exists, it will always be chosen. This map will then be called (with the arguments and keywords if any).

By default this will dispatch as quickly as possible to _element_constructor_() though faster pathways are possible if so desired.

_populate_coercion_lists_(coerce_list=[], action_list=[], convert_list=[], embedding=None, convert_method_name=None, element_constructor=None, init_no_parent=None, unpickling=False)#

This function allows one to specify coercions, actions, conversions and embeddings involving this parent.

IT SHOULD ONLY BE CALLED DURING THE __INIT__ method, often at the end.

INPUT:

  • coerce_list – a list of coercion Morphisms to self and parents with canonical coercions to self

  • action_list – a list of actions on and by self

  • convert_list – a list of conversion Maps to self and

    parents with conversions to self

  • embedding – a single Morphism from self

  • convert_method_name – a name to look for that other elements can implement to create elements of self (e.g. _integer_)

  • init_no_parent – if True omit passing self in as the first argument of element_constructor for conversion. This is useful if parents are unique, or element_constructor is a bound method (this latter case can be detected automatically).

__mul__(x)#

This is a multiplication method that more or less directly calls another attribute _mul_ (single underscore). This is because __mul__ cannot be implemented via inheritance from the parent methods of the category, but _mul_ can be inherited. This is, e.g., used when creating twosided ideals of matrix algebras. See github issue #7797.

EXAMPLES:

sage: MS = MatrixSpace(QQ, 2, 2)                                            # needs sage.modules

This matrix space is in fact an algebra, and in particular it is a ring, from the point of view of categories:

sage: MS.category()                                                         # needs sage.modules
Category of infinite finite dimensional algebras with basis
 over (number fields and quotient fields and metric spaces)
sage: MS in Rings()                                                         # needs sage.modules
True

However, its class does not inherit from the base class Ring:

sage: isinstance(MS, Ring)                                                  # needs sage.modules
False

Its _mul_ method is inherited from the category, and can be used to create a left or right ideal:

sage: # needs sage.modules
sage: MS._mul_.__module__
'sage.categories.rings'
sage: MS * MS.1      # indirect doctest
Left Ideal
(
  [0 1]
  [0 0]
)
 of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: MS * [MS.1, 2]
Left Ideal
(
  [0 1]
  [0 0],

  [2 0]
  [0 2]
)
 of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: MS.1 * MS
Right Ideal
(
  [0 1]
  [0 0]
)
 of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
sage: [MS.1, 2] * MS
Right Ideal
(
  [0 1]
  [0 0],

  [2 0]
  [0 2]
)
 of Full MatrixSpace of 2 by 2 dense matrices over Rational Field
__contains__(x)#

True if there is an element of self that is equal to x under ==, or if x is already an element of self. Also, True in other cases involving the Symbolic Ring, which is handled specially.

For many structures we test this by using __call__() and then testing equality between x and the result.

The Symbolic Ring is treated differently because it is ultra-permissive about letting other rings coerce in, but ultra-strict about doing comparisons.

EXAMPLES:

sage: 2 in Integers(7)
True
sage: 2 in ZZ
True
sage: Integers(7)(3) in ZZ
True
sage: 3/1 in ZZ
True
sage: 5 in QQ
True
sage: I in RR                                                               # needs sage.rings.real_mpfr sage.symbolic
False
sage: RIF(1, 2) in RIF                                                      # needs sage.rings.real_interval_field
True

sage: # needs sage.symbolic
sage: SR(2) in ZZ
True
sage: pi in RIF  # there is no element of RIF equal to pi
False
sage: sqrt(2) in CC
True
sage: pi in RR
True
sage: pi in CC
True
sage: pi in RDF
True
sage: pi in CDF
True

Note that we have

sage: 3/2 in RIF                                                            # needs sage.rings.real_interval_field
True

because 3/2 has an exact representation in RIF (i.e. can be represented as an interval that contains exactly one value):

sage: RIF(3/2).is_exact()                                                   # needs sage.rings.real_interval_field
True

On the other hand, we have

sage: 2/3 in RIF                                                            # needs sage.rings.real_interval_field
False

because 2/3 has no exact representation in RIF. Since RIF(2/3) is a nontrivial interval, it cannot be equal to anything (not even itself):

sage: RIF(2/3).is_exact()                                                   # needs sage.rings.real_interval_field
False
sage: RIF(2/3).endpoints()                                                  # needs sage.rings.real_interval_field
(0.666666666666666, 0.666666666666667)
sage: RIF(2/3) == RIF(2/3)                                                  # needs sage.rings.real_interval_field
False
_coerce_map_from_(S)#

Override this method to specify coercions beyond those specified in coerce_list.

If no such coercion exists, return None or False. Otherwise, it may return either an actual Map to use for the coercion, a callable (in which case it will be wrapped in a Map), or True (in which case a generic map will be provided).

_convert_map_from_(S)#

Override this method to provide additional conversions beyond those given in convert_list.

This function is called after coercions are attempted. If there is a coercion morphism in the opposite direction, one should consider adding a section method to that.

This MUST return a Map from S to self, or None. If None is returned then a generic map will be provided.

_get_action_(S, op, self_on_left)#

Override this method to provide an action of self on S or S on self beyond what was specified in action_list.

This must return an action which accepts an element of self and an element of S (in the order specified by self_on_left).

_an_element_()#

Return an element of self.

Want it in sufficient generality that poorly-written functions will not work when they are not supposed to. This is cached so does not have to be super fast.

EXAMPLES:

sage: QQ._an_element_()
1/2
sage: ZZ['x,y,z']._an_element_()
x
_repr_option(key)#

Metadata about the _repr_() output.

INPUT:

  • key – string. A key for different metadata informations that can be inquired about.

Valid key arguments are:

  • 'ascii_art': The _repr_() output is multi-line ascii art and each line must be printed starting at the same column, or the meaning is lost.

  • 'element_ascii_art': same but for the output of the elements. Used in sage.repl.display.formatter.

  • 'element_is_atomic': the elements print atomically, that is, parenthesis are not required when printing out any of \(x - y\), \(x + y\), \(x^y\) and \(x/y\).

OUTPUT:

Boolean.

EXAMPLES:

sage: ZZ._repr_option('ascii_art')
False
sage: MatrixSpace(ZZ, 2)._repr_option('element_ascii_art')                  # needs sage.modules
True
_init_category_(category)#

Initialize the category framework.

Most parents initialize their category upon construction, and this is the recommended behavior. For example, this happens when the constructor calls Parent.__init__() directly or indirectly. However, some parents defer this for performance reasons. For example, sage.matrix.matrix_space.MatrixSpace does not.

EXAMPLES:

sage: P = Parent()
sage: P.category()
Category of sets
sage: class MyParent(Parent):
....:     def __init__(self):
....:         self._init_category_(Groups())
sage: MyParent().category()
Category of groups
_is_coercion_cached(domain)#

Test whether the coercion from domain is already cached.

EXAMPLES:

sage: R.<XX> = QQ
sage: R._remove_from_coerce_cache(QQ)
sage: R._is_coercion_cached(QQ)
False
sage: _ = R.coerce_map_from(QQ)
sage: R._is_coercion_cached(QQ)
True
_is_conversion_cached(domain)#

Test whether the conversion from domain is already set.

EXAMPLES:

sage: P = Parent()
sage: P._is_conversion_cached(P)
False
sage: P.convert_map_from(P)
Identity endomorphism of <sage.structure.parent.Parent object at ...>
sage: P._is_conversion_cached(P)
True
Hom(codomain, category=None)#

Return the homspace Hom(self, codomain, category).

INPUT:

  • codomain – a parent

  • category – a category or None (default: None) If None, the meet of the category of self and codomain is used.

OUTPUT:

The homspace of all homomorphisms from self to codomain in the category category.

See also

Hom()

EXAMPLES:

sage: R.<x,y> = PolynomialRing(QQ, 2)
sage: R.Hom(QQ)
Set of Homomorphisms from Multivariate Polynomial Ring in x, y over Rational Field to Rational Field

Homspaces are defined for very general Sage objects, even elements of familiar rings:

sage: n = 5; Hom(n,7)
Set of Morphisms from 5 to 7 in Category of elements of Integer Ring
sage: z=(2/3); Hom(z,8/1)
Set of Morphisms from 2/3 to 8 in Category of elements of Rational Field

This example illustrates the optional third argument:

sage: QQ.Hom(ZZ, Sets())
Set of Morphisms from Rational Field to Integer Ring in Category of sets

A parent may specify how to construct certain homsets by implementing a method _Hom_`(codomain, category). See :func:`~sage.categories.homset.Hom() for details.

an_element()#

Returns a (preferably typical) element of this parent.

This is used both for illustration and testing purposes. If the set self is empty, an_element() raises the exception EmptySetError.

This calls _an_element_() (which see), and caches the result. Parent are thus encouraged to override _an_element_().

EXAMPLES:

sage: CDF.an_element()                                                      # needs sage.rings.complex_double
1.0*I
sage: ZZ[['t']].an_element()
t

In case the set is empty, an EmptySetError is raised:

sage: Set([]).an_element()
Traceback (most recent call last):
...
EmptySetError
category()#

EXAMPLES:

sage: P = Parent()
sage: P.category()
Category of sets
sage: class MyParent(Parent):
....:     def __init__(self): pass
sage: MyParent().category()
Category of sets
coerce(x)#

Return x as an element of self, if and only if there is a canonical coercion from the parent of x to self.

EXAMPLES:

sage: QQ.coerce(ZZ(2))
2
sage: ZZ.coerce(QQ(2))
Traceback (most recent call last):
...
TypeError: no canonical coercion from Rational Field to Integer Ring

We make an exception for zero:

sage: V = GF(7)^7                                                           # needs sage.modules
sage: V.coerce(0)                                                           # needs sage.modules
(0, 0, 0, 0, 0, 0, 0)
coerce_embedding()#

Return the embedding of self into some other parent, if such a parent exists.

This does not mean that there are no coercion maps from self into other fields, this is simply a specific morphism specified out of self and usually denotes a special relationship (e.g. sub-objects, choice of completion, etc.)

EXAMPLES:

sage: # needs sage.rings.number_field
sage: x = polygen(ZZ, 'x')
sage: K.<a> = NumberField(x^3 + x^2 + 1, embedding=1)
sage: K.coerce_embedding()
Generic morphism:
  From: Number Field in a with defining polynomial x^3 + x^2 + 1
        with a = -1.465571231876768?
  To:   Real Lazy Field
  Defn: a -> -1.465571231876768?
sage: K.<a> = NumberField(x^3 + x^2 + 1, embedding=CC.gen())
sage: K.coerce_embedding()
Generic morphism:
  From: Number Field in a with defining polynomial x^3 + x^2 + 1
        with a = 0.2327856159383841? + 0.7925519925154479?*I
  To:   Complex Lazy Field
  Defn: a -> 0.2327856159383841? + 0.7925519925154479?*I
coerce_map_from(S)#

Return a Map object to coerce from S to self if one exists, or None if no such coercion exists.

EXAMPLES:

By github issue #12313, a special kind of weak key dictionary is used to store coercion and conversion maps, namely MonoDict. In that way, a memory leak was fixed that would occur in the following test:

sage: import gc
sage: _ = gc.collect()
sage: K = GF(1<<55,'t')                                                     # needs sage.rings.finite_rings
sage: for i in range(50):                                                   # needs sage.rings.finite_rings sage.schemes
....:   a = K.random_element()
....:   E = EllipticCurve(j=a)
....:   b = K.has_coerce_map_from(E)
sage: _ = gc.collect()
sage: len([x for x in gc.get_objects() if isinstance(x, type(E))])          # needs sage.rings.finite_rings sage.schemes
1
convert_map_from(S)#

This function returns a Map from \(S\) to \(self\), which may or may not succeed on all inputs. If a coercion map from S to self exists, then the it will be returned. If a coercion from \(self\) to \(S\) exists, then it will attempt to return a section of that map.

Under the new coercion model, this is the fastest way to convert elements of \(S\) to elements of \(self\) (short of manually constructing the elements) and is used by __call__().

EXAMPLES:

sage: m = ZZ.convert_map_from(QQ)
sage: m
Generic map:
  From: Rational Field
  To:   Integer Ring
sage: m(-35/7)
-5
sage: parent(m(-35/7))
Integer Ring
element_class()#

The (default) class for the elements of this parent

FIXME’s and design issues:

  • If self.Element is “trivial enough”, should we optimize it away with: self.element_class = dynamic_class(“%s.element_class”%self.__class__.__name__, (category.element_class,), self.Element)

  • This should lookup for Element classes in all super classes

get_action(S, op=None, self_on_left=True, self_el=None, S_el=None)#

Returns an action of self on S or S on self.

To provide additional actions, override _get_action_().

Warning

This is not the method that you typically want to call. Instead, call coercion_model.get_action(...) which caches results (this Parent.get_action method does not).

has_coerce_map_from(S)#

Return True if there is a natural map from S to self. Otherwise, return False.

EXAMPLES:

sage: RDF.has_coerce_map_from(QQ)
True
sage: RDF.has_coerce_map_from(QQ['x'])
False
sage: RDF['x'].has_coerce_map_from(QQ['x'])
True
sage: RDF['x,y'].has_coerce_map_from(QQ['x'])
True
hom(im_gens, codomain=None, check=None, base_map=None, category=None, **kwds)#

Return the unique homomorphism from self to codomain that sends self.gens() to the entries of im_gens.

This raises a TypeError if there is no such homomorphism.

INPUT:

  • im_gens – the images in the codomain of the generators of this object under the homomorphism

  • codomain – the codomain of the homomorphism

  • base_map – a map from the base ring to the codomain. If not given, coercion is used.

  • check – whether to verify that the images of generators extend to define a map (using only canonical coercions).

OUTPUT:

A homomorphism self –> codomain

Note

As a shortcut, one can also give an object X instead of im_gens, in which case return the (if it exists) natural map to X.

EXAMPLES:

Polynomial Ring: We first illustrate construction of a few homomorphisms involving a polynomial ring:

sage: R.<x> = PolynomialRing(ZZ)
sage: f = R.hom([5], QQ)
sage: f(x^2 - 19)
6

sage: R.<x> = PolynomialRing(QQ)
sage: f = R.hom([5], GF(7))
Traceback (most recent call last):
...
ValueError: relations do not all (canonically) map to 0
under map determined by images of generators

sage: # needs sage.rings.finite_rings
sage: R.<x> = PolynomialRing(GF(7))
sage: f = R.hom([3], GF(49,'a'))
sage: f
Ring morphism:
  From: Univariate Polynomial Ring in x over Finite Field of size 7
  To:   Finite Field in a of size 7^2
  Defn: x |--> 3
sage: f(x + 6)
2
sage: f(x^2 + 1)
3

Natural morphism:

sage: f = ZZ.hom(GF(5))
sage: f(7)
2
sage: f
Natural morphism:
  From: Integer Ring
  To:   Finite Field of size 5

There might not be a natural morphism, in which case a TypeError is raised:

sage: QQ.hom(ZZ)
Traceback (most recent call last):
...
TypeError: natural coercion morphism from Rational Field to Integer Ring not defined
is_exact()#

Test whether the ring is exact.

Note

This defaults to true, so even if it does return True you have no guarantee (unless the ring has properly overloaded this).

OUTPUT:

Return True if elements of this ring are represented exactly, i.e., there is no precision loss when doing arithmetic.

EXAMPLES:

sage: QQ.is_exact()
True
sage: ZZ.is_exact()
True
sage: Qp(7).is_exact()                                                      # needs sage.rings.padics
False
sage: Zp(7, type='capped-abs').is_exact()                                   # needs sage.rings.padics
False
register_action(action)#

Update the coercion model to use action to act on self.

action should be of type sage.categories.action.Action.

EXAMPLES:

sage: import sage.categories.action
sage: import operator

sage: class SymmetricGroupAction(sage.categories.action.Action):
....:     "Act on a multivariate polynomial ring by permuting the generators."
....:     def __init__(self, G, M, is_left=True):
....:         sage.categories.action.Action.__init__(self, G, M, is_left, operator.mul)
....:
....:     def _act_(self, g, a):
....:         D = {}
....:         for k, v in a.dict().items():
....:             nk = [0]*len(k)
....:             for i in range(len(k)):
....:                 nk[g(i+1)-1] = k[i]
....:             D[tuple(nk)] = v
....:         return a.parent()(D)

sage: # needs sage.groups
sage: R.<x, y, z> = QQ['x, y, z']
sage: G = SymmetricGroup(3)
sage: act = SymmetricGroupAction(G, R)
sage: t = x + 2*y + 3*z

sage: # needs sage.groups
sage: act(G((1, 2)), t)
2*x + y + 3*z
sage: act(G((2, 3)), t)
x + 3*y + 2*z
sage: act(G((1, 2, 3)), t)
3*x + y + 2*z

This should fail, since we have not registered the left action:

sage: G((1,2)) * t                                                          # needs sage.groups
Traceback (most recent call last):
...
TypeError: ...

Now let’s make it work:

sage: # needs sage.groups
sage: R._unset_coercions_used()
sage: R.register_action(act)
sage: G((1, 2)) * t
2*x + y + 3*z
register_coercion(mor)#

Update the coercion model to use \(mor : P \to \text{self}\) to coerce from a parent P into self.

For safety, an error is raised if another coercion has already been registered or discovered between P and self.

EXAMPLES:

sage: K.<a> = ZZ['a']
sage: L.<b> = ZZ['b']
sage: L_into_K = L.hom([-a]) # non-trivial automorphism
sage: K.register_coercion(L_into_K)

sage: K(0) + b
-a
sage: a + b
0
sage: K(b) # check that convert calls coerce first; normally this is just a
-a

sage: L(0) + a in K # this goes through the coercion mechanism of K
True
sage: L(a) in L # this still goes through the convert mechanism of L
True

sage: K.register_coercion(L_into_K)
Traceback (most recent call last):
...
AssertionError: coercion from Univariate Polynomial Ring in b over Integer Ring to Univariate Polynomial Ring in a over Integer Ring already registered or discovered
register_conversion(mor)#

Update the coercion model to use \(\text{mor} : P \to \text{self}\) to convert from P into self.

EXAMPLES:

sage: K.<a> = ZZ['a']
sage: M.<c> = ZZ['c']
sage: M_into_K = M.hom([a]) # trivial automorphism
sage: K._unset_coercions_used()
sage: K.register_conversion(M_into_K)

sage: K(c)
a
sage: K(0) + c
Traceback (most recent call last):
...
TypeError: ...
register_embedding(embedding)#

Add embedding to coercion model.

This method updates the coercion model to use \(\text{embedding} : \text{self} \to P\) to embed self into the parent P.

There can only be one embedding registered; it can only be registered once; and it must be registered before using this parent in the coercion model.

EXAMPLES:

sage: S3 = AlternatingGroup(3)                                              # needs sage.groups
sage: G = SL(3, QQ)                                                         # needs sage.groups
sage: p = S3[2]; p.matrix()                                                 # needs sage.groups
[0 0 1]
[1 0 0]
[0 1 0]

In general one cannot mix matrices and permutations:

sage: # needs sage.groups
sage: G(p)
Traceback (most recent call last):
...
TypeError: unable to convert (1,3,2) to a rational
sage: phi = S3.hom(lambda p: G(p.matrix()), codomain=G)
sage: phi(p)
[0 0 1]
[1 0 0]
[0 1 0]
sage: S3._unset_coercions_used()
sage: S3.register_embedding(phi)

By github issue #14711, coerce maps should be copied when using outside of the coercion system:

sage: phi = copy(S3.coerce_embedding()); phi                                # needs sage.groups
Generic morphism:
  From: Alternating group of order 3!/2 as a permutation group
  To:   Special Linear Group of degree 3 over Rational Field
sage: phi(p)                                                                # needs sage.groups
[0 0 1]
[1 0 0]
[0 1 0]

This does not work since matrix groups are still old-style parents (see github issue #14014):

sage: G(p)                          # not implemented                       # needs sage.groups

Though one can have a permutation act on the rows of a matrix:

sage: G(1) * p                                                              # needs sage.groups
[0 0 1]
[1 0 0]
[0 1 0]

Some more advanced examples:

sage: # needs sage.rings.number_field
sage: x = QQ['x'].0
sage: t = abs(ZZ.random_element(10^6))
sage: K = NumberField(x^2 + 2*3*7*11, "a"+str(t))
sage: a = K.gen()
sage: K_into_MS = K.hom([a.matrix()])
sage: K._unset_coercions_used()
sage: K.register_embedding(K_into_MS)

sage: # needs sage.rings.number_field
sage: L = NumberField(x^2 + 2*3*7*11*19*31,
....:                 "b" + str(abs(ZZ.random_element(10^6))))
sage: b = L.gen()
sage: L_into_MS = L.hom([b.matrix()])
sage: L._unset_coercions_used()
sage: L.register_embedding(L_into_MS)

sage: K.coerce_embedding()(a)                                               # needs sage.rings.number_field
[   0    1]
[-462    0]
sage: L.coerce_embedding()(b)                                               # needs sage.rings.number_field
[      0       1]
[-272118       0]

sage: a.matrix() * b.matrix()                                               # needs sage.rings.number_field
[-272118       0]
[      0    -462]
sage: a.matrix() * b.matrix()                                               # needs sage.rings.number_field
[-272118       0]
[      0    -462]
class sage.structure.parent.Set_generic#

Bases: Parent

Abstract base class for sets.

object()#

Return the underlying object of self.

EXAMPLES:

sage: Set(QQ).object()
Rational Field
sage.structure.parent.is_Parent(x)#

Return True if x is a parent object, i.e., derives from sage.structure.parent.Parent and False otherwise.

EXAMPLES:

sage: from sage.structure.parent import is_Parent
sage: is_Parent(2/3)
False
sage: is_Parent(ZZ)
True
sage: is_Parent(Primes())
True