Search code examples
pythonclassweak-referencespython-internalspython-datamodel

How can I access the weakref object of the class itself through the class?


As far as I know, __weakref__ is a descriptor defined in class, so that if it invoked from the instances of the class, it will give the weakref object:

from weakref import ref

class A:
    pass

obj = A()
wr = ref(obj)
print(obj.__weakref__ is wr)  # True

What about the class A itself? the metaclass type doesn't have __weakref__ descriptor:

print("__weakref__" in type.__dict__)  # False

Why type metaclass doesn't have that descriptor? then where is it stored? how is it possible to access the weakref object (here wr_of_A) from the class?

from weakref import ref

class A:
    pass

wr_of_A = ref(A)
print(A.__weakref__)

# <attribute '__weakref__' of 'A' objects>

Solution

  • It seems that the __weakref__ attribute is exposed in Python as part of the mechanism to allow user created classes be able to opt if they are weak-refereanceble or not as documented in the __slots__ text on the data model. Other than that, even its content being the weakref for the instance seens to be an implementation detail - no other reference to __weakref__ is made on the data model document - which is as a "canonical spec" of Python objetcs as one can get. In the C implementation it is likely the __weakref__ descriptor uses the object's tp_weaklistoffset slot (in the in memory object structure) to retrieve a weakreference object (sorry, I did not dig into the code to check that).

    However, when one goes to type instances, they use the tp_weaklist slot to point to its weak references, using a mechanism that is marked for internal use only, and not exposed to the Python side at all.

    In short: if you are dealing with weakreferences, always use the functions in the weakref module.