Skip to content

Use Py_T_OBJECT_EX instead of _Py_T_OBJECT #107253

Open
@serhiy-storchaka

Description

@serhiy-storchaka

_Py_T_OBJECT is considered legacy PyMemberDef type. The difference between _Py_T_OBJECT and Py_T_OBJECT_EX is that the former returns None if read NULL, while the latter raises AttrributeError. _Py_T_OBJECT manifests itself in two effects:

  1. The default value of the attribute is None, even if it was not initialized in the constructor. It is a desirable behavior in some cases.
  2. After deleting an attribute its value is still None. You cannot truly delete it.

A Py_T_OBJECT_EX member behaves like a normal attribute in Python object, while a _Py_T_OBJECT member behaves like in the case when the corresponding class attribute was set to None:

class A:
    attr = None

x = A()
assert x.attr is None
x.attr = 5
assert x.attr == 5
del x.attr
assert x.attr is None

What if replace _Py_T_OBJECT with Py_T_OBJECT_EX? It turns out that you can replace it in 105 sites but 31 sites should keep _Py_T_OBJECT to make existing tests pass. This is not a very reliable result because the tests may not cover all cases. On the other hand, some tests are too picky and check the attributes of a newly created uninitialized object, even if they are normally initialized.

In any case, we can take these results and replace _Py_T_OBJECT with Py_T_OBJECT_EX on case by case basis.

@vstinner @encukou

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions