strategy question about method name uniformity

167 views
Skip to first unread message

Martin R

unread,
Sep 24, 2025, 2:12:22 AMSep 24
to sage-devel
At https://github.com/sagemath/sage/pull/40875, Frédéric is harmonizing the prefix of the names of methods returning the number of facets (points, vertices, parts, etc.) of polytopes to `n_facets`, before it was `nfacets`.

While I think this is very good, I would rather go one tiny step further, and harmonize both to `number_of_facets`, or, in fact, just make `number_of_facets` an alias.

My question here is: is anybody strictly against this?  More precisely:

Any method returning the number of some components of a structure should be named `number_of_xxx`, other aliases are OK.

I did a quick grep, the current situation is as follows:

grep -r --include=*.{py,pyx} --color=auto -nH --null -e "def[^(]* number_of_.*(" *
125 matches

grep -r --include=*.{py,pyx} --color=auto -nH --null -e "def[^(]* num_.*(" *
22 matches
most important example: graph.num_verts

grep -r --include=*.{py,pyx} --color=auto -nH --null -e "def[^(]* n_.*(" *
97 matches
mostly geometry/polyhedron

most important example for nxxx is of course ngens, and I'm afraid we shouldn't rename that one.  But there is also `nvars` (in sat/solvers), `ncols` and `nrows` for matrices, `ncusps` in `arithgroup`, and the polytope methods.

Finally, there are a few really odd ones, which I stumble across every other month (and hate): 

combinat/binary_tree.py:1752:    def left_children_node_number(self, direction='left'):
combinat/binary_tree.py:2600:    def hook_number(self):
combinat/abstract_tree.py:1159:    def node_number(self):
combinat/permutation.py:2442:    def longest_increasing_subsequences_number(self):
combinat/posets/posets.py:2714:    def relations_number(self):

Martin

Tobia...@gmx.de

unread,
Sep 24, 2025, 9:05:23 AMSep 24
to sage-devel
I like the initiative of having a global naming scheme. No preference from my side on which one.

As a data point: numpy/scipy seem to be using the `nxxx` pattern:

and "count_xyz" if it's a method (which I do like):

In general, they seem to try to not use "number of xyz" but use a more descriptive term (eg. matrix.shape instead of matrix.ncols/nrows).

Vincent Macri

unread,
Sep 24, 2025, 10:39:57 AMSep 24
to sage-...@googlegroups.com
I agree that consistency is good. I prefer underscore naming, I find it more readable and it's what PEP 8 recommends. I think number_of_facets is a bit too long for my tastes (mostly because we try to adhere to line length limits and long names make that annoying). If I were writing that code I'd probably call it num_facets.

Of course how much of a problem a long name is depends on how often it's used. If we renamed the matrix nrows and ncols to number_of_rows and number_of_columns then it would be very annoying to write an if statement to check the matrix size against some other values and have that line fit in 80 characters (sure you can wrap it, but I think that hurts readability). Perhaps number_of_facets is not used so much that this is an actual problem. But I think num_facets is a happy medium that is both clear and short enough to not be annoying, which means that naming scheme can be used consistently.

For methods that are used very frequently (ncols, nrows, ngens, etc.) I think it's probably fine to leave them as-is. We could add aliases for num_cols, num_rows, etc. if we want.

I recently added functionality to our documentation builder (https://github.com/sagemath/sage/pull/40753) to detect aliased functions and methods and not duplicate them in the HTML docs (it now says "alias of [link to original]", before it just duplicated the docstring including all the examples) so bloating the documentation with aliases isn't really a problem anymore (in case someone was worried about that).

One thing I would note is that changing the name of nfacets is technically a breaking change and there should be an alias for the old name with a deprecation warning in place for however long our depreciation period is.

Also, thank you Frédéric for all the refactoring and code cleanup work you've been doing!

Vincent Macri (he/him)

Martin R

unread,
Sep 24, 2025, 2:23:01 PMSep 24
to sage-devel
There are about 100 distinct methods named `number_of_xxx`.  I'm a bit sceptical that changing or aliasing these to `num_xxx` is a good idea - mostly because of tab completion.

Martin

Vincent Macri

unread,
Sep 24, 2025, 4:46:48 PMSep 24
to 'Martin R' via sage-devel
On 2025-09-24 12:23 p.m., 'Martin R' via sage-devel wrote:
> There are about 100 distinct methods named `number_of_xxx`.  I'm a bit
> sceptical that changing or aliasing these to `num_xxx` is a good idea
> - mostly because of tab completion.

If that's the naming scheme that's already established in our code base
then I think go ahead with `number_of_xxx` (keeping in mind our
deprecation policy of course). We can always add shortened aliases later
if a name ends up being too unwieldy. I'd leave nrows, ncols, ngens or
other names that are used very extensively alone though.

It would be nice to have something in our developer guide about common
naming conventions for situations like this to have somewhere to point
to for consistency.

Kwankyu Lee

unread,
Sep 24, 2025, 9:05:30 PMSep 24
to sage-devel
I regard 

"num_xxx", "n_xxx" and "nxxx"

as different abbreviations of "number_of_xxx". So to abbreviate "number", we are using "num" and "n". I think we should choose just one. I prefer "n" (and hate "num").

Hence in my opinion, we should keep 

(1) "number_of_" like in "number_of_facets"
(2) "n_" like in "n_facets"
(3) "n" like in "ngens" 

and use (3) for names that occur very frequently.

Kwankyu

Frédéric Chapoton

unread,
Sep 25, 2025, 7:42:13 AMSep 25
to sage-devel
Hello,

I think it will be hard to achieve consistency on this matter. Unless of course somebody wants to spent the next few years doing that. Any volunteer ?

(0) I think we should allow "n*" and "n_*" and "number_of_*" only. I have a preference for "n_*".

(1) My current proposal is to use "n_*" everywhere in geometry/ This is a small thing, and ready for review.

(2) one could also easily get rid of all "num_*" as there are not so many. This is just annoying for graphs,

(3) concerning alias versus deprecation, I would prefer to deprecate. But we can also keep the aliases and let our heirs do the deprecation.

Frédéric



Martin R

unread,
Oct 1, 2025, 3:47:37 AMOct 1
to sage-devel
Dear all!

There are now pull requests (see below) that attempt more uniformity.  I think that the following de facto consensus emerged:

1. in general, we keep the old names as aliases, but replace occurences of the old names also in the codebase
2. we use n_xxx for methods that are used frequently and number_of_xxx for the rest

Some of the pull requests have already positive review, some I made "needs: info", because I do not want to make a silly decision.  I don't think that any of them are already merged.

In general, I see two arguments in favour of the pull requests, and one against:

* it makes it easier for the casual user to remember the method names
* it makes it possible to grep for such methods (as opposed to `nrows`)
* the aliases pollute the name space

The last point implies that we should be careful in choosing the new method names.  For example, I just realize that Graph.number_of_connected_components might be better just Graph.n_components.  So, please voice your opinion now :-)

A few people (including myself) warn that the old methods should not be deprecated, even though this might be tempting for better aesthetics.  We have to keep in mind that there is code outside that uses the old method names which we do not control, and which is run only rarely.  For example, there is a code snippet for almost every statistic in the findstat database, many of which would be affected in this particular case.  It would be a shame if these would stop working.

Best wishes,

Martin

Martin R

unread,
Oct 1, 2025, 4:36:09 AMOct 1
to sage-devel
There is also an overview at

Message has been deleted

TB

unread,
Oct 7, 2025, 6:29:13 PMOct 7
to sage-...@googlegroups.com
Like others, I think consistent naming is a good idea, except when it is
not(...), and the specific details are harder to get right. Thanks to
those who try to improve the Sage API.

One nice advantage of names such as facets_{num,number,count} is
discoverability via tab-completion, especially if the user already knows
the facets() method exists. It happens that IPython supports [1]
glob-style matches such as obj.*abc*?, to find all attributes containing
"abc", but I suppose most people do not use this feature, so it will be
harder to know that n_facets() exists. On the other hand, in Sage,
trying to complete obj.is_* is a good way to start inspecting an object,
so maybe obj.n_* will be a good starting point for "simple" enumerations.

A partial remedy is adding a SEEALSO block in the factes() docstring
referencing n_factes(), assuming users read the docs. If n_facets() is
more efficient than len(facets()), e.g., in time or memory, then it also
merits a mention in the same place.

Regards,
TB

[1]
https://ipython.readthedocs.io/en/stable/interactive/python-ipython-diff.html
> --
> You received this message because you are subscribed to the Google
> Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sage-devel+...@googlegroups.com <mailto:sage-
> devel+un...@googlegroups.com>.
> To view this discussion visit https://groups.google.com/d/msgid/sage-
> devel/804af5fd-c14e-4670-ad1c-e7529bd516c1n%40googlegroups.com <https://
> groups.google.com/d/msgid/sage-devel/804af5fd-c14e-4670-ad1c-
> e7529bd516c1n%40googlegroups.com?utm_medium=email&utm_source=footer>.

Nicolas M. Thiery

unread,
Oct 8, 2025, 10:58:01 AMOct 8
to sage-...@googlegroups.com

Thanks everyone for the work on consistency! It is both most welcome
and tough to balance usability, explorability and backward
compatibility.

Just 2 cents so that we have the full picture in mind in this special
case: in addition to X.n_Ys() and X.number_of_Ys() we also have
X.Ys().cardinality(). Of course, this is only relevant if it's worth
to explicitely model the set of all Ys. Typical use cases:

- providing several methods (cardinality, __iter__, random_element,
...).
- enabling further constructions from the set (cartesian products,
vector space indexed by the set, ...)

Cheers,
Nicolas
> > To view this discussion visit https://secure-web.cisco.com/1296ljPEiQ876pW8IQQ4BnVh76zq1gC8n9-2296iwYpT5mxIeZRSIofFoezygAYN5HhHR5AJWJ1wbeZpuDAlXAlcjF5GXCLkJz94J27W1P3Y9fyfELykiO3Ntdnf-vPsL_w8k7ibCKAikmNwv6rLuWMTpw0Th1yR8z2aneIwKnh6NI_EOMxulqNBw9FKmhXMmtAe3wxCmeXbzMjLi7W5XC2kG8gRr4AKkb9MWf_3qwE2nbUxI4cKO2ZNlMDBzt0ecbdXGHIAqrTtkGR0z0e2G504Zl242OZuetKKYyVt-QTMASEF_B2uHbMbNK5e1lh5_zBE7jsIUIvwodHvdZsPAez8OQS0XZFvgp5B-QaOudFokZxl-TXloLV_BmxAZZNwZjsOwLAX33qq5W9P6wuqxgUsP_1h8hxBJnbm7g1lMhcNlzSYktthlqRFJIQrJSP1g/https%3A%2F%2Fgroups.google.com%2Fd%2Fmsgid%2Fsage-
> --
> You received this message because you are subscribed to the Google Groups "sage-devel" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
> To view this discussion visit https://secure-web.cisco.com/1EI21lb-aOEK2OwJjQK8-rCMfAVOOkEeVPGeSbp9ydV2A1AKDcXZtUH77UWos99R6jJg-kz6nzznHgTMiSo7D04FO_s1NOSyDIDVNlumQ21An2AfqRxeUsOxe2t603FwozzNV2YGPkF-SehcgLQCZ-5fkSHxEtowwYZhfCUSlFP77kzaTYvV9gr1WnxlSLHnZ0aNDkWrPq6j_PC8FBYlEDlNNEmu4gqze2NycE_QZM88GTluAXzcgG3HlaPBfFxvNrG65jDvHWl3PWQRhg0f-A_L5WHLCf2Gx4cXxteeKClmPxuazJIxS9S2ftdJyenosz8yiux1Y5E2DwmKMidcuxqsqOpHhfIiGSJVNjNIzhvivddPJIzofVDmThuJugWtLLciwBwOrVNKg1qXXlgk1AoYlQ9Zc_EctFwnwWGCyf7-7QwvIYbmxOwrFDznDwsUT/https%3A%2F%2Fgroups.google.com%2Fd%2Fmsgid%2Fsage-devel%2Fc03f2b66-34bd-45aa-93e5-6d178f83a2b2%2540gmail.com
>
Nicolas
--
Nicolas M. Thiéry "Isil" <Nicolas...@universite-paris-saclay.fr>
http://Nicolas.Thiery.name/
Reply all
Reply to author
Forward
0 new messages