Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
10668: Explicitly document that Element.__getattr__ can also be usefu…
Browse files Browse the repository at this point in the history
…l when refining categories
  • Loading branch information
nthiery committed Jun 22, 2014
1 parent fc5b0f1 commit 4b67d7c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
9 changes: 5 additions & 4 deletions src/sage/rings/polynomial/polynomial_quotient_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,11 @@ class of the category, and store the current class of the quotient
sage: [s for s in dir(Q.category().element_class) if not s.startswith('_')]
['cartesian_product', 'gcd', 'is_idempotent', 'is_one', 'is_unit', 'lcm', 'lift', 'xgcd']
As one can see, the elements are now inheriting additional methods: lcm and gcd. Even though
``Q.an_element()`` belongs to the old and not to the new element class, it still inherits
the new methods from the category of fields::
As one can see, the elements are now inheriting additional
methods: lcm and gcd. Even though ``Q.an_element()`` belongs to
the old and not to the new element class, it still inherits the
new methods from the category of fields, thanks to
:meth:`Element.__getattr__`::
sage: isinstance(Q.an_element(),Q.element_class)
False
Expand All @@ -287,7 +289,6 @@ class of the category, and store the current class of the quotient
sage: TestSuite(Q(x)).run()
sage: isinstance(Q(x), Q.element_class)
True
"""
Element = PolynomialQuotientRingElement

Expand Down
41 changes: 32 additions & 9 deletions src/sage/structure/element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,40 @@ cdef class Element(sage_object.SageObject):

def __getattr__(self, str name):
"""
Let cat be the category of the parent of ``self``. This
method emulates ``self`` being an instance of both ``Element``
and ``cat.element_class``, in that order, for attribute
lookup.
Lookup a method or attribute from the category abstract classes.
NOTE:
Let ``P`` be a parent in a category ``C``. Usually the methods
of ``C.element_class`` are made directly available to elements
of ``P`` via standard class inheritance. This is not the case
any more if the elements of ``P`` are instances of an
extension type. See :class:`Category`. for details.
The purpose of this method is to emulate this inheritance: for
``e`` and element of ``P``, if an attribute or method
``e.foo`` is not found in the super classes of ``e``, it's
looked up manually in ``C.element_class`` and bound to ``e``.
.. NOTES::
- Attributes beginning with two underscores but not ending
with an unnderscore are considered private and are thus
exempted from the lookup in ``cat.element_class``.
Attributes beginning with two underscores but not ending with
an unnderscore are considered private and are thus exempted
from the lookup in ``cat.element_class``.
- The attribute or method is actually looked up in
``P._abstract_element_class``. In most cases this is
just an alias for ``C.element_class``, but some parents,
notably homsets, customizes this to let elements also
inherit from other abstract classes. See
:meth:`Parent._abstract_element_class` and
:meth:`Homset._abstract_element_class` for details.
- This mechanism may also enter into action when the
category of `P` is refined on the fly, leaving
previously constructed elements in an outdated element
class.
See :class:`~sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_generic`
for an example.
EXAMPLES:
Expand Down Expand Up @@ -330,7 +354,6 @@ cdef class Element(sage_object.SageObject):
Traceback (most recent call last):
...
AttributeError: 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint' object has no attribute '__foo'
"""
if (name.startswith('__') and not name.endswith('_')):
dummy_error_message.cls = type(self)
Expand Down

0 comments on commit 4b67d7c

Please sign in to comment.