Reputation: 45281
This is more or less how I would track the number of class instances, since __new__
is called every time one is made:
class MyClass():
def __new__(klass):
try:
klass.__instances = klass.__instances + 1
except NameError:
klass.__instances = 1
return super(MyClass,klass).__new__(klass)
Is there a magic method that is called when a new reference to a specific instance of a class is made? If not, is there a straight forward way to implement one? For example:
class MyClass():
def __init__(self):
self.__ref = 1
print(self,"created.")
def __new_reference(self):
self.__ref = self.__ref + 1
print("Reference to",self,"added.")
def __del_reference(self):
self.__ref = self.__ref - 1
print("Reference to",self,"deleted.")
So now:
L1 = []
L2 = []
L1.append(MyClass()) #<MyClass object> created
L1[0].__ref #1
L2.append(L1[0]) #Reference to <MyClass object> added.
L2[0].__ref #2
L1.pop(0) #Reference to <MyClass object> deleted.
L2[0].__ref #1
Edit:
Here's the problem I thought I would try to solve using reference tracking.
My idea is to have an object A
instance that contains multiple (weak) references to object B
s. There is a separate list containing all valid B
s. There is a list of all the A
s as well (thousands). The desired behavior is that when any one B
is removed from the B
list, for any object A
to become None
if it contained a reference to that particular B
removed from the B
list.
Upvotes: 1
Views: 634
Reputation: 45281
I just thought of a simple way to almost accomplish this, and it's probably good enough for my situation.
All I have to do is be sure to call the object every time it is referenced. This isn't quite as neat and tidy as I was hoping for, but it does allow tracking of the number of references that I'm interested in (though it does not track all references).
Here's a code sample to illustrate:
class MyClass():
def __init__(self):
self._ref = 1
print(self,"created.")
def __call__(self, new_ref=True):
if new_ref is True: self.__new_reference()
elif new_ref is False: self.__del_reference()
return self
def __new_reference(self):
self._ref = self._ref + 1
print("Reference to",self,"added.")
def __del_reference(self):
self._ref = self._ref - 1
print("Reference to",self,"deleted.")
Now I can do this:
L1 = []
L2 = []
L1.append(MyClass()) #<MyClass object> created.
print(L1[0]._ref) #1
L2.append(L1[0](True)) #Reference to <MyClass object> added.
print(L2[0]._ref) #2
L1.pop(0)(False) #Reference to <MyClass object> deleted.
print(L2[0]._ref) #1
I just have to remember to call my special object every time I add or delete it.
Alternatively, I could subclass a special container class for the special objects that calls the object with the appropriate argument when it is added or removed. Not sure if it's worth the effort to do this though.
Upvotes: 0
Reputation: 129517
As far as I know there is no magic method that does this, but maybe you could use sys.getrefcount()
:
Return the reference count of the object. The count returned is generally one higher than you might expect, because it includes the (temporary) reference as an argument to
getrefcount()
.
Using your example:
>>> import sys
>>> class MyClass: pass
...
>>> L1 = []
>>> L2 = []
>>> L1.append(MyClass())
>>> sys.getrefcount(L1[0])
2
>>> L2.append(L1[0])
>>> sys.getrefcount(L1[0])
3
>>> del L1[0]
>>> sys.getrefcount(L2[0])
2
Upvotes: 2