Python's gc module has several useful functions, but it sounds like gc.get_referrers() is what you're looking for. Here's an example:
import gc
def foo():
a = [2, 4, 6]
b = [1, 4, 7]
l = [a, b]
d = dict(a=a)
return l, d
l, d = foo()
r1 = gc.get_referrers(l[0])
r2 = gc.get_referrers(l[1])
print r1
print r2
When I run that, I see the following output:
[[[2, 4, 6], [1, 4, 7]], {'a': [2, 4, 6]}]
[[[2, 4, 6], [1, 4, 7]]]
You can see that the first line is l and d, and the second line is just l.
In my brief experiments, I've found that the results are not always this clean. Interned strings and tuples, for example, have more referrers than you would expect.
Answer from Don Kirkby on Stack OverflowPython's gc module has several useful functions, but it sounds like gc.get_referrers() is what you're looking for. Here's an example:
import gc
def foo():
a = [2, 4, 6]
b = [1, 4, 7]
l = [a, b]
d = dict(a=a)
return l, d
l, d = foo()
r1 = gc.get_referrers(l[0])
r2 = gc.get_referrers(l[1])
print r1
print r2
When I run that, I see the following output:
[[[2, 4, 6], [1, 4, 7]], {'a': [2, 4, 6]}]
[[[2, 4, 6], [1, 4, 7]]]
You can see that the first line is l and d, and the second line is just l.
In my brief experiments, I've found that the results are not always this clean. Interned strings and tuples, for example, have more referrers than you would expect.
Python's standard library has gc module containing garbage collector API. One of the function you possible want to have is
gc.get_objects()
This function returns list of all objects currently tracked by garbage collector. The next step is to analyze it.
If you know the object you want to track you can use sys module's getrefcount function:
>>> x = object()
>>> sys.getrefcount(x)
2
>>> y = x
>>> sys.getrefcount(x)
3
I have a linked list
node_0 = Node(11)
node_1 = Node(22)
node_2 = Node(33)
node_3 = Node(44)
node_0.next_node = node_1
node_1.next_node = node_2
node_2.next_node = node_3
linked_list_obj = LinkedList(node_0)
In this problem, you only have access to node_2 and I want to delete node_2 without changing values between nodes.
In linked list, if you want to delete node_2, you have to access to node_1.
So I thought I can use gc.get_referrers(node_2) to get the object of node_1
node_previous = gc.get_referrers(node_2) "return the list of objects" according to Python doc
print(node_previous[0])
>> {'data': 22, 'next_node': <Chapter14.Chapter14Q1.Node object at 0x0000020A74881F40>}
But that is a dictionary that logged the data of node_1. It's not actually not node_1.
Because if you print node_1, you get the actual object.
print(node_1)
>> <Chapter14.Chapter14Q1.Node object at 0x0000020A74881F70>
I want gc.get_referrers(node_2) to return the actual object (node_1) not the log of the object in a dictionary. Is this possible?
Is it possible to get all the objects referencing a given object in Python? - Stack Overflow
Python object references - Stack Overflow
Newest Questions - Stack Overflow
List of object references in python - Stack Overflow
As you can see, it's impossible to find them all.
>>> sys.getrefcount(1)
791
>>> sys.getrefcount(2)
267
>>> sys.getrefcount(3)
98
I'd like to clarify some misinformation here. This doesn't really have anything to do with the fact that "ints are immutable". When you write a = 2 you are assigning a and a alone to something different -- it has no effect on b and c.
If you were to modify a property of a however, then it would effect b and c. Hopefully this example better illustrates what I'm talking about:
>>> a = b = c = [1] # assign everyone to the same object
>>> a, b, c
([1], [1], [1])
>>> a[0] = 2 # modify a member of a
>>> a, b, c
([2], [2], [2]) # everyone gets updated because they all refer to the same object
>>> a = [3] # assign a to a new object
>>> a, b, c
([3], [2], [2]) # b and c are not affected
Take a look at the gc module. This is the closest you can get.
A good site is, e.g., this one.
This is just an idea: If you know where the object is created, I can imagine that you know the potential variables and classes that can have a reference to your object. So you may be able to use the id function to check who is referencing what.
I hope it helps
If you actually ran that in Java, I think you'd find it probably prints out true because of string interning, but that's somewhat irrelevant.
I'm not sure what you mean by "replaces it with the object it is referring to". What actually happens is that when you write a == b, Python calls a.__eq__(b), which is just like any other method call on a with b as an argument.
If you want an equivalent to Java-like ==, use the is operator: a is b. That compares whether the name a refers to the same object as b, regardless of whether they compare as equal.
Python interning:
>>> a = "hello"
>>> b = "hello"
>>> c = "world"
>>> id(a)
4299882336
>>> id(b)
4299882336
>>> id(c)
4299882384
Short strings tend to get interned automatically, explaining why a is b == True. See here for more.
In Python, assignment operator binds the result of the right hand side expression to the name from the left hand side expression.
So, when you say
a = Foo(2)
b = [a]
you have created a Foo object and refer it with a. Then you create a list b with the reference to the Foo object (a). That is why b[0].value prints 2.
But,
a = Foo(3)
creates a new Foo object and refers that with the name a. So, now a refers to the new Foo object not the old object. But the list still has reference to the old object only. That is why it still prints 2.
b[0] points to the object you initially created with Foo(2). When you do a = Foo(3), you create a new object and call it a. You did not change b in any way.
The behavior is because of exactly what you said: b holds a reference to an object. It does not hold hold a reference to the name you used to refer to that object. So the object in b[0] does not know anything about any variable called a. Assigning a new value to a has no effect on b.