Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/doc/en/thematic_tutorials/coercion_and_categories.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ as this base class still provides a few more methods than a general parent::
sage: [p for p in dir(Field) if p not in dir(Parent)]
['_CommutativeRing__fraction_field',
'__iter__',
'__len__',
'__rxor__',
'__xor__',
'_coerce_',
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/enumerated_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ def _list_from_iterator(self):
sage: list(MyIntegers) # indirect test
Traceback (most recent call last):
...
NotImplementedError
NotImplementedError: infinite set
"""
try:
if self._list is not None:
Expand Down
16 changes: 16 additions & 0 deletions src/sage/categories/sets_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1911,6 +1911,22 @@ def is_finite(self):
"""
return False

def __len__(self):
"""
Return the length.

As this is not defined for infinite sets,
this raises a :exc:`ValueError`.

EXAMPLES::

sage: len(QQ)
Traceback (most recent call last):
...
ValueError: infinite set
"""
raise ValueError('infinite set')

def is_empty(self):
r"""
Return whether this set is empty.
Expand Down
8 changes: 4 additions & 4 deletions src/sage/combinat/words/finite_word.py
Original file line number Diff line number Diff line change
Expand Up @@ -6758,10 +6758,10 @@ def to_monoid_element(self):
"""
from sage.monoids.free_monoid import FreeMonoid
try:
l = list(self.parent().alphabet())
except AttributeError:
l = self.letters()
M = FreeMonoid(len(l), l)
li = list(self.parent().alphabet())
except (AttributeError, ValueError, NotImplementedError):
li = self.letters()
M = FreeMonoid(len(li), li)
return M(self)

def is_christoffel(self) -> bool:
Expand Down
7 changes: 3 additions & 4 deletions src/sage/functions/piecewise.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,8 @@ def domain(self, parameters, variable):
sage: f.domain()
[0, 2)
"""
intervals = []
for domain, func in parameters:
intervals += list(domain)
intervals = [interval for domain, func in parameters
for interval in iter(domain)]
return RealSet(*intervals)

def __len__(self, parameters, variable):
Expand All @@ -430,7 +429,7 @@ def __len__(self, parameters, variable):

def expressions(self, parameters, variable):
"""
Return the individual domains.
Return the individual expressions.

See also :meth:`~domains`.

Expand Down
4 changes: 2 additions & 2 deletions src/sage/matrix/matrix_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,7 @@ def __len__(self):
sage: len(MatrixSpace(QQ,3,2))
Traceback (most recent call last):
...
TypeError: len() of unsized object
ValueError: infinite set
"""
return len(self.base_ring())**(self.nrows() * self.ncols())

Expand Down Expand Up @@ -1747,7 +1747,7 @@ def __iter__(self):
sage: a = list(MS)
Traceback (most recent call last):
...
NotImplementedError: len() of an infinite set
ValueError: infinite set
"""
# Make sure that we can iterate over the base ring
base_ring = self.base_ring()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/integer_ring.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ cdef class IntegerRing_class(CommutativeRing):
sage: list(ZZ)
Traceback (most recent call last):
...
NotImplementedError: len() of an infinite set
NotImplementedError: infinite set

sage: ZZ.is_finite()
False
Expand Down
15 changes: 0 additions & 15 deletions src/sage/rings/rational_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,21 +290,6 @@ def __reduce__(self):
"""
return RationalField, tuple()

def __len__(self):
"""
Return the number of elements in ``self``.

Since this does not have a size, this throws a :exc:`TypeError`.

EXAMPLES::

sage: len(QQ)
Traceback (most recent call last):
...
TypeError: len() of unsized object
"""
raise TypeError('len() of unsized object')

def construction(self):
r"""
Return a pair ``(functor, parent)`` such that ``functor(parent)``
Expand Down
39 changes: 21 additions & 18 deletions src/sage/rings/ring.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@ cdef class Ring(ParentWithGens):
7
sage: QQ.cardinality()
+Infinity

Check length::

sage: len(Integers(24))
24
sage: len(RR)
Traceback (most recent call last):
...
ValueError: infinite set
sage: len(CC)
Traceback (most recent call last):
...
ValueError: infinite set
sage: len(QQ['x'])
Traceback (most recent call last):
...
ValueError: infinite set
sage: len(QQ)
Traceback (most recent call last):
...
ValueError: infinite set
"""
def __init__(self, base, names=None, normalize=True, category=None):
"""
Expand Down Expand Up @@ -273,24 +294,6 @@ cdef class Ring(ParentWithGens):
"""
raise NotImplementedError("object does not support iteration")

def __len__(self):
r"""
Return the cardinality of this ring if it is finite, else raise
a :exc:`NotImplementedError`.

EXAMPLES::

sage: len(Integers(24))
24
sage: len(RR)
Traceback (most recent call last):
...
NotImplementedError: len() of an infinite set
"""
if self.is_finite():
return self.cardinality()
raise NotImplementedError('len() of an infinite set')

def __xor__(self, n):
r"""
Trap the operation ``^``.
Expand Down
2 changes: 2 additions & 0 deletions src/sage/sets/real_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,8 @@ def n_components(self):
"""
return len(self._intervals)

__len__ = n_components

def cardinality(self):
r"""
Return the cardinality of the subset of the real line.
Expand Down
47 changes: 45 additions & 2 deletions src/sage/structure/parent.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1053,9 +1053,52 @@ cdef class Parent(sage.structure.category_object.CategoryObject):
return NotImplemented
return meth(x)

#############################################################################
def __len__(self):
"""
Return the length when possible.

The default implementation of ``__len__`` on parent redirects to the
super class (in case of multiple inheritance) or to the category. This
redirection is necessary when the parent is a Cython class (aka
extension class) because in that case the parent class does not inherit
from the ``ParentMethods`` of the category.

Concrete implementations of parents can freely overwrite this default
method.

TESTS::

sage: len(ZZ)
Traceback (most recent call last):
...
NotImplementedError: infinite set
sage: len(QQ)
Traceback (most recent call last):
...
ValueError: infinite set
sage: len(RR)
Traceback (most recent call last):
...
ValueError: infinite set
sage: len(IntegerModRing(6))
6
"""
if not isinstance(self, Parent):
return NotImplemented
try:
# get __len__ from super class
meth = super().__len__
except AttributeError:
# get __len__ from category in case the parent is a Cython class
try:
meth = (<Parent> self).getattr_from_category('__len__')
except AttributeError:
return NotImplemented
return meth()

##########################################################################
# Containment testing
#############################################################################
##########################################################################
def __contains__(self, x):
r"""
``True`` if there is an element of ``self`` that is equal to ``x``
Expand Down
Loading