Commutative rings#

class sage.categories.commutative_rings.CommutativeRings(base_category)[source]#

Bases: CategoryWithAxiom_singleton

The category of commutative rings

commutative rings with unity, i.e. rings with commutative * and a multiplicative identity

EXAMPLES:

sage: C = CommutativeRings(); C
Category of commutative rings
sage: C.super_categories()
[Category of rings, Category of commutative monoids]
>>> from sage.all import *
>>> C = CommutativeRings(); C
Category of commutative rings
>>> C.super_categories()
[Category of rings, Category of commutative monoids]
class CartesianProducts(category, *args)[source]#

Bases: CartesianProductsCategory

extra_super_categories()[source]#

Let Sage knows that Cartesian products of commutative rings is a commutative ring.

EXAMPLES:

sage: CommutativeRings().Commutative().CartesianProducts().extra_super_categories()
[Category of commutative rings]
sage: cartesian_product([ZZ, Zmod(34),
....:                    QQ, GF(5)]) in CommutativeRings()
True
>>> from sage.all import *
>>> CommutativeRings().Commutative().CartesianProducts().extra_super_categories()
[Category of commutative rings]
>>> cartesian_product([ZZ, Zmod(Integer(34)),
...                    QQ, GF(Integer(5))]) in CommutativeRings()
True
class ElementMethods[source]#

Bases: object

class Finite(base_category)[source]#

Bases: CategoryWithAxiom_singleton

Check that Sage knows that Cartesian products of finite commutative rings is a finite commutative ring.

EXAMPLES:

sage: cartesian_product([Zmod(34),
....:                    GF(5)]) in Rings().Commutative().Finite()
True
>>> from sage.all import *
>>> cartesian_product([Zmod(Integer(34)),
...                    GF(Integer(5))]) in Rings().Commutative().Finite()
True
class ParentMethods[source]#

Bases: object

cyclotomic_cosets(q, cosets=None)[source]#

Return the (multiplicative) orbits of q in the ring.

Let \(R\) be a finite commutative ring. The group of invertible elements \(R^*\) in \(R\) gives rise to a group action on \(R\) by multiplication. An orbit of the subgroup generated by an invertible element \(q\) is called a \(q\)-cyclotomic coset (since in a finite ring, each invertible element is a root of unity).

These cosets arise in the theory of minimal polynomials of finite fields, duadic codes and combinatorial designs. Fix a primitive element \(z\) of \(GF(q^k)\). The minimal polynomial of \(z^s\) over \(GF(q)\) is given by

\[M_s(x) = \prod_{i \in C_s} (x - z^i),\]

where \(C_s\) is the \(q\)-cyclotomic coset mod \(n\) containing \(s\), \(n = q^k - 1\).

Note

When \(R = \ZZ / n \ZZ\) the smallest element of each coset is sometimes called a coset leader. This function returns sorted lists so that the coset leader will always be the first element of the coset.

INPUT:

  • q – an invertible element of the ring

  • cosets – an optional lists of elements of self. If provided, the function only return the list of cosets that contain some element from cosets.

OUTPUT:

A list of lists.

EXAMPLES:

sage: Zmod(11).cyclotomic_cosets(2)
[[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
sage: Zmod(15).cyclotomic_cosets(2)
[[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]]
>>> from sage.all import *
>>> Zmod(Integer(11)).cyclotomic_cosets(Integer(2))
[[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
>>> Zmod(Integer(15)).cyclotomic_cosets(Integer(2))
[[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]]

Since the group of invertible elements of a finite field is cyclic, the set of squares is a particular case of cyclotomic coset:

sage: # needs sage.rings.finite_rings
sage: K = GF(25, 'z')
sage: a = K.multiplicative_generator()
sage: K.cyclotomic_cosets(a**2, cosets=[1])
[[1, 2, 3, 4, z + 1, z + 3,
  2*z + 1, 2*z + 2, 3*z + 3,
  3*z + 4, 4*z + 2, 4*z + 4]]
sage: sorted(b for b in K if not b.is_zero() and b.is_square())
[1, 2, 3, 4, z + 1, z + 3,
 2*z + 1, 2*z + 2, 3*z + 3,
 3*z + 4, 4*z + 2, 4*z + 4]
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> K = GF(Integer(25), 'z')
>>> a = K.multiplicative_generator()
>>> K.cyclotomic_cosets(a**Integer(2), cosets=[Integer(1)])
[[1, 2, 3, 4, z + 1, z + 3,
  2*z + 1, 2*z + 2, 3*z + 3,
  3*z + 4, 4*z + 2, 4*z + 4]]
>>> sorted(b for b in K if not b.is_zero() and b.is_square())
[1, 2, 3, 4, z + 1, z + 3,
 2*z + 1, 2*z + 2, 3*z + 3,
 3*z + 4, 4*z + 2, 4*z + 4]

We compute some examples of minimal polynomials:

sage: # needs sage.rings.finite_rings
sage: K = GF(27, 'z')
sage: a = K.multiplicative_generator()
sage: R.<X> = PolynomialRing(K, 'X')
sage: a.minimal_polynomial('X')
X^3 + 2*X + 1

sage: cyc3 = Zmod(26).cyclotomic_cosets(3, cosets=[1]); cyc3
[[1, 3, 9]]
sage: prod(X - a**i for i in cyc3[0])                               # needs sage.rings.finite_rings
X^3 + 2*X + 1
sage: (a**7).minimal_polynomial('X')                                # needs sage.rings.finite_rings
X^3 + X^2 + 2*X + 1
sage: cyc7 = Zmod(26).cyclotomic_cosets(3, cosets=[7]); cyc7
[[7, 11, 21]]
sage: prod(X - a**i for i in cyc7[0])                               # needs sage.rings.finite_rings
X^3 + X^2 + 2*X + 1
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> K = GF(Integer(27), 'z')
>>> a = K.multiplicative_generator()
>>> R = PolynomialRing(K, 'X', names=('X',)); (X,) = R._first_ngens(1)
>>> a.minimal_polynomial('X')
X^3 + 2*X + 1

>>> cyc3 = Zmod(Integer(26)).cyclotomic_cosets(Integer(3), cosets=[Integer(1)]); cyc3
[[1, 3, 9]]
>>> prod(X - a**i for i in cyc3[Integer(0)])                               # needs sage.rings.finite_rings
X^3 + 2*X + 1
>>> (a**Integer(7)).minimal_polynomial('X')                                # needs sage.rings.finite_rings
X^3 + X^2 + 2*X + 1
>>> cyc7 = Zmod(Integer(26)).cyclotomic_cosets(Integer(3), cosets=[Integer(7)]); cyc7
[[7, 11, 21]]
>>> prod(X - a**i for i in cyc7[Integer(0)])                               # needs sage.rings.finite_rings
X^3 + X^2 + 2*X + 1

Cyclotomic cosets of fields are useful in combinatorial design theory to provide so called difference families (see Wikipedia article Difference_set and difference_family). This is illustrated on the following examples:

sage: K = GF(5)
sage: a = K.multiplicative_generator()                              # needs sage.libs.pari
sage: H = K.cyclotomic_cosets(a**2, cosets=[1, 2]); H               # needs sage.rings.finite_rings
[[1, 4], [2, 3]]
sage: sorted(x - y for D in H for x in D for y in D if x != y)      # needs sage.rings.finite_rings
[1, 2, 3, 4]

sage: K = GF(37)
sage: a = K.multiplicative_generator()                              # needs sage.libs.pari
sage: H = K.cyclotomic_cosets(a**4, cosets=[1]); H                  # needs sage.rings.finite_rings
[[1, 7, 9, 10, 12, 16, 26, 33, 34]]
sage: sorted(x - y for D in H for x in D for y in D if x != y)      # needs sage.rings.finite_rings
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ..., 33, 34, 34, 35, 35, 36, 36]
>>> from sage.all import *
>>> K = GF(Integer(5))
>>> a = K.multiplicative_generator()                              # needs sage.libs.pari
>>> H = K.cyclotomic_cosets(a**Integer(2), cosets=[Integer(1), Integer(2)]); H               # needs sage.rings.finite_rings
[[1, 4], [2, 3]]
>>> sorted(x - y for D in H for x in D for y in D if x != y)      # needs sage.rings.finite_rings
[1, 2, 3, 4]

>>> K = GF(Integer(37))
>>> a = K.multiplicative_generator()                              # needs sage.libs.pari
>>> H = K.cyclotomic_cosets(a**Integer(4), cosets=[Integer(1)]); H                  # needs sage.rings.finite_rings
[[1, 7, 9, 10, 12, 16, 26, 33, 34]]
>>> sorted(x - y for D in H for x in D for y in D if x != y)      # needs sage.rings.finite_rings
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ..., 33, 34, 34, 35, 35, 36, 36]

The method cyclotomic_cosets works on any finite commutative ring:

sage: R = cartesian_product([GF(7), Zmod(14)])
sage: a = R((3,5))
sage: R.cyclotomic_cosets((3,5), [(1,1)])
[[(1, 1), (2, 11), (3, 5), (4, 9), (5, 3), (6, 13)]]
>>> from sage.all import *
>>> R = cartesian_product([GF(Integer(7)), Zmod(Integer(14))])
>>> a = R((Integer(3),Integer(5)))
>>> R.cyclotomic_cosets((Integer(3),Integer(5)), [(Integer(1),Integer(1))])
[[(1, 1), (2, 11), (3, 5), (4, 9), (5, 3), (6, 13)]]
extra_super_categories()[source]#

Let Sage know that finite commutative rings are Noetherian.

EXAMPLES:

sage: CommutativeRings().Finite().extra_super_categories()
[Category of noetherian rings]
>>> from sage.all import *
>>> CommutativeRings().Finite().extra_super_categories()
[Category of noetherian rings]
class ParentMethods[source]#

Bases: object

derivation(arg=None, twist=None)[source]#

Return the twisted or untwisted derivation over this ring specified by arg.

Note

A twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation for short) is an additive map \(d\) satisfying the following axiom for all \(x, y\) in the domain:

\[d(xy) = \theta(x) d(y) + d(x) y.\]

INPUT:

  • arg – (optional) a generator or a list of coefficients that defines the derivation

  • twist – (optional) the twisting homomorphism

EXAMPLES:

sage: R.<x,y,z> = QQ[]
sage: R.derivation()                                                        # needs sage.modules
d/dx
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> R.derivation()                                                        # needs sage.modules
d/dx

In that case, arg could be a generator:

sage: R.derivation(y)                                                       # needs sage.modules
d/dy
>>> from sage.all import *
>>> R.derivation(y)                                                       # needs sage.modules
d/dy

or a list of coefficients:

sage: R.derivation([1,2,3])                                                 # needs sage.modules
d/dx + 2*d/dy + 3*d/dz
>>> from sage.all import *
>>> R.derivation([Integer(1),Integer(2),Integer(3)])                                                 # needs sage.modules
d/dx + 2*d/dy + 3*d/dz

It is not possible to define derivations with respect to a polynomial which is not a variable:

sage: R.derivation(x^2)                                                     # needs sage.modules
Traceback (most recent call last):
...
ValueError: unable to create the derivation
>>> from sage.all import *
>>> R.derivation(x**Integer(2))                                                     # needs sage.modules
Traceback (most recent call last):
...
ValueError: unable to create the derivation

Here is an example with twisted derivations:

sage: R.<x,y,z> = QQ[]
sage: theta = R.hom([x^2, y^2, z^2])
sage: f = R.derivation(twist=theta); f                                      # needs sage.modules
0
sage: f.parent()                                                            # needs sage.modules
Module of twisted derivations over Multivariate Polynomial Ring in x, y, z
 over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> theta = R.hom([x**Integer(2), y**Integer(2), z**Integer(2)])
>>> f = R.derivation(twist=theta); f                                      # needs sage.modules
0
>>> f.parent()                                                            # needs sage.modules
Module of twisted derivations over Multivariate Polynomial Ring in x, y, z
 over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)

Specifying a scalar, the returned twisted derivation is the corresponding multiple of \(\theta - id\):

sage: R.derivation(1, twist=theta)                                          # needs sage.modules
[x |--> x^2, y |--> y^2, z |--> z^2] - id
sage: R.derivation(x, twist=theta)                                          # needs sage.modules
x*([x |--> x^2, y |--> y^2, z |--> z^2] - id)
>>> from sage.all import *
>>> R.derivation(Integer(1), twist=theta)                                          # needs sage.modules
[x |--> x^2, y |--> y^2, z |--> z^2] - id
>>> R.derivation(x, twist=theta)                                          # needs sage.modules
x*([x |--> x^2, y |--> y^2, z |--> z^2] - id)
derivation_module(codomain=None, twist=None)[source]#

Return the module of derivations over this ring.

INPUT:

  • codomain – an algebra over this ring or a ring homomorphism whose domain is this ring or None (default: None); if it is a morphism, the codomain of derivations will be the codomain of the morphism viewed as an algebra over self through the given morphism; if None, the codomain will be this ring

  • twist – a morphism from this ring to codomain or None (default: None); if None, the coercion map from this ring to codomain will be used

Note

A twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation for short) is an additive map \(d\) satisfying the following axiom for all \(x, y\) in the domain:

\[d(xy) = \theta(x) d(y) + d(x) y.\]

EXAMPLES:

sage: R.<x,y,z> = QQ[]
sage: M = R.derivation_module(); M                                          # needs sage.modules
Module of derivations over
 Multivariate Polynomial Ring in x, y, z over Rational Field
sage: M.gens()                                                              # needs sage.modules
(d/dx, d/dy, d/dz)
>>> from sage.all import *
>>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3)
>>> M = R.derivation_module(); M                                          # needs sage.modules
Module of derivations over
 Multivariate Polynomial Ring in x, y, z over Rational Field
>>> M.gens()                                                              # needs sage.modules
(d/dx, d/dy, d/dz)

We can specify a different codomain:

sage: K = R.fraction_field()
sage: M = R.derivation_module(K); M                                         # needs sage.modules
Module of derivations
 from Multivariate Polynomial Ring in x, y, z over Rational Field
   to Fraction Field of
      Multivariate Polynomial Ring in x, y, z over Rational Field
sage: M.gen() / x                                                           # needs sage.modules
1/x*d/dx
>>> from sage.all import *
>>> K = R.fraction_field()
>>> M = R.derivation_module(K); M                                         # needs sage.modules
Module of derivations
 from Multivariate Polynomial Ring in x, y, z over Rational Field
   to Fraction Field of
      Multivariate Polynomial Ring in x, y, z over Rational Field
>>> M.gen() / x                                                           # needs sage.modules
1/x*d/dx

Here is an example with a non-canonical defining morphism:

sage: ev = R.hom([QQ(0), QQ(1), QQ(2)])
sage: ev
Ring morphism:
  From: Multivariate Polynomial Ring in x, y, z over Rational Field
  To:   Rational Field
  Defn: x |--> 0
        y |--> 1
        z |--> 2
sage: M = R.derivation_module(ev)                                           # needs sage.modules
sage: M                                                                     # needs sage.modules
Module of derivations
 from Multivariate Polynomial Ring in x, y, z over Rational Field
   to Rational Field
>>> from sage.all import *
>>> ev = R.hom([QQ(Integer(0)), QQ(Integer(1)), QQ(Integer(2))])
>>> ev
Ring morphism:
  From: Multivariate Polynomial Ring in x, y, z over Rational Field
  To:   Rational Field
  Defn: x |--> 0
        y |--> 1
        z |--> 2
>>> M = R.derivation_module(ev)                                           # needs sage.modules
>>> M                                                                     # needs sage.modules
Module of derivations
 from Multivariate Polynomial Ring in x, y, z over Rational Field
   to Rational Field

Elements in \(M\) acts as derivations at \((0,1,2)\):

sage: # needs sage.modules
sage: Dx = M.gen(0); Dx
d/dx
sage: Dy = M.gen(1); Dy
d/dy
sage: Dz = M.gen(2); Dz
d/dz
sage: f = x^2 + y^2 + z^2
sage: Dx(f)  # = 2*x evaluated at (0,1,2)
0
sage: Dy(f)  # = 2*y evaluated at (0,1,2)
2
sage: Dz(f)  # = 2*z evaluated at (0,1,2)
4
>>> from sage.all import *
>>> # needs sage.modules
>>> Dx = M.gen(Integer(0)); Dx
d/dx
>>> Dy = M.gen(Integer(1)); Dy
d/dy
>>> Dz = M.gen(Integer(2)); Dz
d/dz
>>> f = x**Integer(2) + y**Integer(2) + z**Integer(2)
>>> Dx(f)  # = 2*x evaluated at (0,1,2)
0
>>> Dy(f)  # = 2*y evaluated at (0,1,2)
2
>>> Dz(f)  # = 2*z evaluated at (0,1,2)
4

An example with a twisting homomorphism:

sage: theta = R.hom([x^2, y^2, z^2])
sage: M = R.derivation_module(twist=theta); M                               # needs sage.modules
Module of twisted derivations over Multivariate Polynomial Ring in x, y, z
 over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
>>> from sage.all import *
>>> theta = R.hom([x**Integer(2), y**Integer(2), z**Integer(2)])
>>> M = R.derivation_module(twist=theta); M                               # needs sage.modules
Module of twisted derivations over Multivariate Polynomial Ring in x, y, z
 over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)

See also

derivation()

frobenius_endomorphism(n=1)[source]#

Return the Frobenius endomorphism.

INPUT:

  • n – a nonnegative integer (default: 1)

OUTPUT:

The \(n\)-th power of the absolute arithmetic Frobenius endomorphism on this commutative ring.

EXAMPLES:

sage: K.<u> = PowerSeriesRing(GF(5))
sage: Frob = K.frobenius_endomorphism(); Frob
Frobenius endomorphism x |--> x^5 of Power Series Ring in u
 over Finite Field of size 5
sage: Frob(u)
u^5
>>> from sage.all import *
>>> K = PowerSeriesRing(GF(Integer(5)), names=('u',)); (u,) = K._first_ngens(1)
>>> Frob = K.frobenius_endomorphism(); Frob
Frobenius endomorphism x |--> x^5 of Power Series Ring in u
 over Finite Field of size 5
>>> Frob(u)
u^5

We can specify a power:

sage: f = K.frobenius_endomorphism(2); f
Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u
 over Finite Field of size 5
sage: f(1+u)
1 + u^25
>>> from sage.all import *
>>> f = K.frobenius_endomorphism(Integer(2)); f
Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u
 over Finite Field of size 5
>>> f(Integer(1)+u)
1 + u^25
is_commutative()[source]#

Return whether the ring is commutative.

The answer is True only if the category is a sub-category of CommutativeRings.

It is recommended to use instead R in Rings().Commutative().

EXAMPLES:

sage: QQ.is_commutative()
True
sage: QQ['x,y,z'].is_commutative()
True
>>> from sage.all import *
>>> QQ.is_commutative()
True
>>> QQ['x,y,z'].is_commutative()
True
over(base=None, gen=None, gens=None, name=None, names=None)[source]#

Return this ring, considered as an extension of base.

INPUT:

  • base – a commutative ring or a morphism or None (default: None); the base of this extension or its defining morphism

  • gen – a generator of this extension (over its base) or None (default: None);

  • gens – a list of generators of this extension (over its base) or None (default: None);

  • name – a variable name or None (default: None)

  • names – a list or a tuple of variable names or None (default: None)

EXAMPLES:

We construct an extension of finite fields:

sage: # needs sage.rings.finite_rings
sage: F = GF(5^2)
sage: k = GF(5^4)
sage: z4 = k.gen()
sage: K = k.over(F); K                                                  # needs sage.modules
Field in z4 with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base
>>> from sage.all import *
>>> # needs sage.rings.finite_rings
>>> F = GF(Integer(5)**Integer(2))
>>> k = GF(Integer(5)**Integer(4))
>>> z4 = k.gen()
>>> K = k.over(F); K                                                  # needs sage.modules
Field in z4 with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base

If not explicitly given, the default generator of the top ring (here k) is used and the same name is kept:

sage: K.gen()                                                           # needs sage.modules sage.rings.finite_rings
z4
sage: K(z4)                                                             # needs sage.modules sage.rings.finite_rings
z4
>>> from sage.all import *
>>> K.gen()                                                           # needs sage.modules sage.rings.finite_rings
z4
>>> K(z4)                                                             # needs sage.modules sage.rings.finite_rings
z4

However, it is possible to specify another generator and/or another name. For example:

sage: # needs sage.modules sage.rings.finite_rings
sage: Ka = k.over(F, name='a'); Ka
Field in a with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base
sage: Ka.gen()
a
sage: Ka(z4)
a

sage: # needs sage.modules sage.rings.finite_rings
sage: Kb = k.over(F, gen=-z4+1, name='b')
sage: Kb
Field in b with defining polynomial x^2 + z2*x + 4 over its base
sage: Kb.gen()
b
sage: Kb(-z4+1)
b
>>> from sage.all import *
>>> # needs sage.modules sage.rings.finite_rings
>>> Ka = k.over(F, name='a'); Ka
Field in a with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base
>>> Ka.gen()
a
>>> Ka(z4)
a

>>> # needs sage.modules sage.rings.finite_rings
>>> Kb = k.over(F, gen=-z4+Integer(1), name='b')
>>> Kb
Field in b with defining polynomial x^2 + z2*x + 4 over its base
>>> Kb.gen()
b
>>> Kb(-z4+Integer(1))
b

Note that the shortcut K.<a> is also available:

sage: KKa.<a> = k.over(F)                                               # needs sage.modules sage.rings.finite_rings
sage: KKa is Ka                                                         # needs sage.modules sage.rings.finite_rings
True
>>> from sage.all import *
>>> KKa = k.over(F, names=('a',)); (a,) = KKa._first_ngens(1)# needs sage.modules sage.rings.finite_rings
>>> KKa is Ka                                                         # needs sage.modules sage.rings.finite_rings
True

Building an extension on top of another extension is allowed:

sage: L = GF(5^12).over(K); L                                           # needs sage.modules sage.rings.finite_rings
Field in z12 with defining polynomial
 x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base
sage: L.base_ring()                                                     # needs sage.modules sage.rings.finite_rings
Field in z4 with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base
>>> from sage.all import *
>>> L = GF(Integer(5)**Integer(12)).over(K); L                                           # needs sage.modules sage.rings.finite_rings
Field in z12 with defining polynomial
 x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base
>>> L.base_ring()                                                     # needs sage.modules sage.rings.finite_rings
Field in z4 with defining polynomial
 x^2 + (4*z2 + 3)*x + z2 over its base

The successive bases of an extension are accessible via the method sage.rings.ring_extension.RingExtension_generic.bases():

sage: L.bases()                                                         # needs sage.modules sage.rings.finite_rings
[Field in z12 with defining polynomial
  x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base,
 Field in z4 with defining polynomial
  x^2 + (4*z2 + 3)*x + z2 over its base,
 Finite Field in z2 of size 5^2]
>>> from sage.all import *
>>> L.bases()                                                         # needs sage.modules sage.rings.finite_rings
[Field in z12 with defining polynomial
  x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base,
 Field in z4 with defining polynomial
  x^2 + (4*z2 + 3)*x + z2 over its base,
 Finite Field in z2 of size 5^2]

When base is omitted, the canonical base of the ring is used:

sage: S.<x> = QQ[]
sage: E = S.over(); E                                                   # needs sage.modules
Univariate Polynomial Ring in x over Rational Field over its base
sage: E.base_ring()                                                     # needs sage.modules
Rational Field
>>> from sage.all import *
>>> S = QQ['x']; (x,) = S._first_ngens(1)
>>> E = S.over(); E                                                   # needs sage.modules
Univariate Polynomial Ring in x over Rational Field over its base
>>> E.base_ring()                                                     # needs sage.modules
Rational Field

Here is an example where base is a defining morphism:

sage: # needs sage.modules sage.rings.number_field
sage: k.<a> = QQ.extension(x^2 - 2)
sage: l.<b> = QQ.extension(x^4 - 2)
sage: f = k.hom([b^2])
sage: L = l.over(f)
sage: L
Field in b with defining polynomial x^2 - a over its base
sage: L.base_ring()
Number Field in a with defining polynomial x^2 - 2
>>> from sage.all import *
>>> # needs sage.modules sage.rings.number_field
>>> k = QQ.extension(x**Integer(2) - Integer(2), names=('a',)); (a,) = k._first_ngens(1)
>>> l = QQ.extension(x**Integer(4) - Integer(2), names=('b',)); (b,) = l._first_ngens(1)
>>> f = k.hom([b**Integer(2)])
>>> L = l.over(f)
>>> L
Field in b with defining polynomial x^2 - a over its base
>>> L.base_ring()
Number Field in a with defining polynomial x^2 - 2

Similarly, one can create a tower of extensions:

sage: # needs sage.modules sage.rings.number_field
sage: K = k.over()
sage: L = l.over(Hom(K, l)(f)); L
Field in b with defining polynomial x^2 - a over its base
sage: L.base_ring()
Field in a with defining polynomial x^2 - 2 over its base
sage: L.bases()
[Field in b with defining polynomial x^2 - a over its base,
 Field in a with defining polynomial x^2 - 2 over its base,
 Rational Field]
>>> from sage.all import *
>>> # needs sage.modules sage.rings.number_field
>>> K = k.over()
>>> L = l.over(Hom(K, l)(f)); L
Field in b with defining polynomial x^2 - a over its base
>>> L.base_ring()
Field in a with defining polynomial x^2 - 2 over its base
>>> L.bases()
[Field in b with defining polynomial x^2 - a over its base,
 Field in a with defining polynomial x^2 - 2 over its base,
 Rational Field]