For me it is not clear why the simple and direct code that avoids an avatar of a new class is not good enough, so it is hard to design a good class, that makes next steps easy to work. The passage about "diluting a precious namespace" is not really an issue from a pragmatical point of view. The namespace is "something else" while writing code.
The line polytopes.depleted_cube(6).strange_facet().vertices()
must be an orientation wish. So let us see what can be realized from it. What is polytopes
? I will use p
as a short cut.
sage: p = polytopes
sage: print(p)
<sage.geometry.polyhedron.library.Polytopes object at 0x7b0addf97e00>
sage: type(p)
<class 'sage.geometry.polyhedron.library.Polytopes'>
So this is a class. It has many methods. For instance:
sage: p.__init__
<method-wrapper '__init__' of Polytopes object at 0x7b0addf97e00>
And also a lot of other published methods. We avoid the "privat" ones, those starting with an underscore (at least), and pick only the first ten:
sage: [met for met in dir(p) if not met.startswith('_')][:10]
['Birkhoff_polytope',
'Gosset_3_21',
'Kirkman_icosahedron',
'associahedron',
'bitruncated_six_hundred_cell',
'buckyball',
'cantellated_one_hundred_twenty_cell',
'cantellated_six_hundred_cell',
'cantitruncated_one_hundred_twenty_cell',
'cantitruncated_six_hundred_cell']
sage:
(Remove the slicing [:10]
to see all of them.)
Of course, depleted_cube
is not on the list, but we have for instance the h-starting methods:
sage: [met for met in dir(p) if met.startswith('h')]
['hypercube', 'hypersimplex']
So what is polytopes.hypercube
?
sage: type(p.hypercube)
<class 'method'>
It is a method. This method returns an object of an other class. So we jump from place to place.
What does it return? To get the related code of the method we type:
sage: p.hypercube??
and scroll down. The last lines are:
return parent([cp, [], []], [ieqs, []], convert=convert, Vrep_minimal=True, Hrep_minimal=True, pref_rep='Hrep')
File: /usr/lib/python3.13/site-packages/sage/geometry/polyhedron/library.py
Type: method
We see where the code lives, and what it returns (in some if-case). The involved variables are defined in advance, for instance:
parent = Polyhedra(ZZ, dim, backend=backend)
But this "thing", parent
, is what kind of an object? We must know where we are, when using it, and how to make from a file path the right python object:
sage: my_parent = sage.geometry.polyhedron.library
sage: my_parent.Polyhedra
<function Polyhedra at 0x7b0ade0ca480>
So Polyhedra
is a function published in the same py-module. It is not a class, it returns an object, and this object is used in the next construction. (So trying to do "the same" means to define a function - not a class - depleted_cube
in the same framework. Why should we inherit a "kind-of-a-factory" class, to have an other such class with a new function, when we can define this function in a direct manner?) Then for instance p.hypercube(3)
returns an object.
An object of which class?
sage: C = p.hypercube(3)
sage: type(C)
<class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category.element_class'>
Do we really want to inherit from such a "thing". To better get the story of the thing, let us ask:
sage: type(sage)
<class 'module'>
sage: type(sage.geometry)
<class 'module'>
sage: type(sage.geometry.polyhedron)
<class 'module'>
sage: type(sage.geometry.polyhedron.parent)
<class 'module'>
sage: type(sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[82], line 1
----> 1 type(sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category)
AttributeError: module 'sage.geometry.polyhedron.parent' has no attribute 'Polyhedra_ZZ_ppl_with_category'
sage:
At this point my wish to trace back the places finally and inherit a class is vanishing. There is no reason to search for such a hidden class or function. In fact, a doc string tells us:
def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *,
ambient_space=None, base_ring=None):
r"""
Construct a suitable parent class for polyhedra.
INPUT:
- ``base_ring`` -- a ring; currently there are backends for `\ZZ`,
`\QQ`, and `\RDF`
- ``ambient_dim`` -- integer; the ambient space dimension
- ``ambient_space`` -- a free module
- ``backend`` -- string. The name of the backend for computations. There are
several backends implemented:
* ``backend="ppl"`` uses the Parma Polyhedra Library
* ``backend="cdd"`` uses CDD
* ``backend="normaliz"`` uses normaliz
* ``backend="polymake"`` uses polymake
* ``backend="field"`` a generic Sage implementation
OUTPUT:
A parent class for polyhedra over the given base ring if the
backend supports it. If not, the parent base ring can be larger
(for example, `\QQ` instead of `\ZZ`). If there is no
implementation at all, a :exc:`ValueError` is raised.
So Polyhedra
is a function returning a class. (Which has its constructor, some methods, and so on.)
In other words, the libraries are constructing first a dual, advanced world, then from this world the final geometric objects in suitable dimensions over suitable rings. As an user of the library, it is not easy and/or it does not make sense to extend a package outside of the package. (Since it may change, thus thing stop to work or to be maintainable.)
probably using
Polyhedra_base