11

All:

a = 1
b = a
c = b

Now I want to get a list of object 1 tagged, which is [a, b, c]. How could I do this?

BTW, how to call variable "a" here officially? I know so far it is a "object tag" for the object, but I have no idea what is the term of it.

Thanks!

why do I need this:

a = b = c = 1 
print a, b, c 
1 1 1
a = 2
print a, b, c 
2 1 1

in other language such as C, a,b,c should be 2 if I re-assign a = 2, but in python, there's no such thing like reference, so the only way to change all the value of a b c is a = b = c = 2 so far as I know, that is why purposed to get all reference of an object.

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
user478514
  • 3,859
  • 10
  • 33
  • 42
  • Why? Why do you want this? What possible purposes can it serve? – S.Lott Dec 03 '10 at 04:04
  • 2
    Now you only repeated /what/ you want, not /why/ you want it. – pillmuncher Dec 03 '10 at 17:18
  • The reason `b` and `c` are not altered when you change the value of `a` is because the `int` type is immutable. You'd need a simple container before you could do it like that. – Chris Morgan Dec 03 '10 at 23:21
  • 1
    @ChrisMorgan: It's not because `int` is immutable. If those were objects, you'd still have the same effect. `a` is being reassigned to something different, but `b` and `c` aren't touched. If `a` was an object *and* you modified a *property* of `a`, *then* the other 2 would be updated as well. – mpen Jul 01 '12 at 18:53

7 Answers7

11

As you can see, it's impossible to find them all.

>>> sys.getrefcount(1)
791
>>> sys.getrefcount(2)
267
>>> sys.getrefcount(3)
98
Kabie
  • 10,489
  • 1
  • 38
  • 45
9

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
mpen
  • 272,448
  • 266
  • 850
  • 1,236
5

I think you might be interested in objgraph. It allows you to traverse the object graph in memory, or dump a PNG of your object graph. It's useful for debugging memory leaks.

See this page: http://mg.pov.lt/objgraph/

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
3

It is not possible to find all references to a given object in Python. It is not even possible to find all objects or all references in Python. (The CPython function gc.get_objects does this, but it is not portable across Python implementations.)

You can use dir() or locals() to find all variables that exist at some scope in the program. But if objects have been defined in other places, you could miss them with this method.

Heatsink
  • 7,721
  • 1
  • 25
  • 36
  • I think your answer is factually wrong, considering that `objgraph` does exactly that—find references to a given object. – Erik Kaplun Aug 09 '13 at 16:54
  • @ErikAllik This is possible only in some Python implementations, because it relies on non-portable features of the GC. For example, it will not work in Jython. I'll mention it in the answer, though. – Heatsink Aug 09 '13 at 18:19
2

What you're asking isn't very practical and isn't possible. Here's one crazy way of doing it:

>>> a = 1
>>> b = a
>>> c = b
>>> locals()
{'a': 1, 'c': 1, 'b': 1, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': None}
>>> [key for key, value in locals().items() if value == 1]
['a', 'c', 'b']
>>> globals()
{'a': 1, 'c': 1, 'b': 1, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': None}
>>> [key for key, value in globals().items() if value == 1]
['a', 'c', 'b']
Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • thanks, that is one approach, but that has no means for me in semantic, my question is I try to express the "variable" a, b, c is a "ref" of the value 1, they are same reference of value 1, but if I define another d = 1, there's no doubt id(d) is same as id(a), but here I think it has the mean of d.value = a.value but not means d = a although they DO tag same object in python I known. – user478514 Dec 03 '10 at 16:33
  • @user478514: that's demonstrating slightly that *it can't be done*. – Chris Morgan Dec 03 '10 at 22:05
  • 1
    @user478514: The fact that "a = 1; d = 1; id(a) == id(d) -> True" is a coincidence. As an optimization, python has an internal list of all integers from -5 to 256: any reference to one of those integers gets a reference to the one from this internal list. If you try the same test in general, with another class or even an integer greater than 256, you'll find that this returns False. E.g. a = 300; d = 300; id(a) == id(d) -> False – mikenerone Oct 31 '12 at 21:48
1

First of all in C, "=" is a value assignment and does not create a reference. More specifically when you write a=b=1 what happens is this.

(1) b=1 gets evaluated, assigns 1 to b and then returns 1, so the expression becomes a=1

(2) a=1 gets evaluated, assigns 1 to b and then returns 1 which is not used anywhere.

Then a=1 changes only a as expected.

In python things are a bit more complicated as every variable is a reference, but it treats numbers differently because they are immutable. In short when you write a=1 and b=1, then a is b returns True. But changing one will not change the other.

This however does not happen with objects, with them a reference works as expected. So if you want to do what you describe maybe you should define a new object that holds the value you want and assign this to a variable.

tst
  • 1,117
  • 2
  • 10
  • 21
0

Look at pyjack. Its replace_all_refs function seems to work pretty well to replace all references to an object. Note: Doesn't work well with string objects.

user2682863
  • 3,097
  • 1
  • 24
  • 38