Created
January 22, 2020 12:52
-
-
Save riga/0a751a4555276804b54fdfeb97629a6a to your computer and use it in GitHub Desktop.
Python reference count manipulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
import sys | |
import gc | |
import ctypes | |
# configuration of Py_IncRef and Py_DecRef | |
_c_inc_ref = ctypes.pythonapi.Py_IncRef | |
_c_inc_ref.argtypes = [ctypes.py_object] | |
_c_dec_ref = ctypes.pythonapi.Py_DecRef | |
_c_dec_ref.argtypes = [ctypes.py_object] | |
def inc_ref(obj, n=1): | |
""" | |
Increases the reference count of an object *obj* by *n*. | |
""" | |
for _ in range(n): | |
_c_inc_ref(obj) | |
def dec_ref(obj, n=1, collect=True): | |
""" | |
Decreases the reference count of an object *obj* by *n*. When *collect* is *True*, the garbage | |
collector is initiated afterwards. | |
""" | |
for _ in range(n): | |
_c_dec_ref(obj) | |
if collect: | |
gc.collect() | |
def ref_count(obj): | |
""" | |
Returns the number of references to an object *obj*. | |
""" | |
# subtract 3 for: function argument, reference in getrefcount, and the function stack | |
return sys.getrefcount(obj) - 3 | |
# return len(gc.get_referrers(obj)) - 1 | |
if __name__ == "__main__": | |
# some tests which print (expected value, actual value) | |
obj = object() | |
print(1, ref_count(obj)) | |
obj2 = obj | |
print(2, ref_count(obj)) | |
del obj2 | |
print(1, ref_count(obj)) | |
inc_ref(obj) | |
print(2, ref_count(obj)) | |
dec_ref(obj) | |
print(1, ref_count(obj)) | |
dec_ref(obj) | |
print("random number", ref_count(obj)) # obj is garbage collected |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment