Skip to content

Helpers for getting references to singletons #91927

Description

@hvenev

Feature or enhancement

There are lots of places where a new reference to a singleton is needed. This is done in a variety of ways:

1.  obj = Py_NewRef(Py_None);

2.  obj = Py_None;
    Py_INCREF(obj);

3.  Py_INCREF(Py_None);
    obj = Py_None;

4.  obj = Py_None;
    Py_INCREF(Py_None);

5.  obj = (Py_INCREF(Py_None), Py_None);

The proposal is to add another way that can hopefully become idiomatic:

6.  obj = Py_RefNone();

The following singletons are considered:

  • None
  • NotImplemented
  • Ellipsis
  • False
  • True

In the internal API, helpers for the following singletons can be added:

  • The strings returned by _Py_ID and _Py_STR
  • The integers 0 and 1

Pitch

One advantage of using the new helpers is that it abstracts away the necessity to increment the reference count if immortal instances are implemented.

Alternatively, if immortal instances aren't implemented and all singletons are made per-interpreter, it will slightly reduce the performance overhead by making sure that the singletons are only looked up once (compared to patterns 3, 4, and 5, where the singletons are obtained twice).

Previous discussion

Activity

  1. vstinner commented on Nov 15, 2022

    @vstinner
    Member

    The problem of adding Py_RefNone() is that it grows up the Python C API by 1 more function which should be:

    • tested
    • documented
    • new comers have to learn about it

    If we consider 5 singletons, we're talking about adding 5 functions. The problem is that the Python C API is already very big and is painful to maintain: see statistics on the C API.

    IMO Py_NewRef(Py_None) is short and it doesn't require to learn a new API but combine two well defined API:

    • Py_None: borrowed reference to the None singleton
    • Py_NewRef(): create a new strong reference

    See issue #99300 which replaces Py_INCREF() with Py_NewRef(). You can see there that Py_NewRef() is applicable to many cases.

    @erlend-aasland: I propose closing this issue in favor of using Py_NewRef(Py_None).

    For example, the Py_RETURN_NONE is now simply defined as return Py_NewRef(Py_None).

  2. vstinner commented on Nov 15, 2022

    @vstinner
    Member

    By the way, my experimental PR #18301 added Py_GetNone() and Py_GetNoneRef() (2 functions just for None!), but the trend is more towards immortal objects: PEP 683.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions