I was playing around with sys.getrefcount in Python 3.7 on Windows. I tried the following:
>>> import sys
>>> x = "this is an arbitrary string"
>>> sys.getrefcount(x)
2
I understand that one of the references is x, and the other is the parameter used internally within sys.getrefcount. This seems to work no matter the type to which x is initialized. However, I noticed some weird behavior when I don't assign before I pass:
>>> import sys
>>> sys.getrefcount("arbitrary string")
2
>>> sys.getrefcount(1122334455)
2
>>> sys.getrefcount(1122334455+1)
2
>>> sys.getrefcount(frozenset())
2
>>> sys.getrefcount(set())
1
>>> sys.getrefcount(object())
1
>>> sys.getrefcount([])
1
>>> sys.getrefcount(lambda x: x)
1
>>> sys.getrefcount(range(1122334455))
1
>>> sys.getrefcount(dict())
1
>>> sys.getrefcount(())
8341
>>> sys.getrefcount(tuple())
8340
>>> sys.getrefcount(list("arbitrary string"))
1
>>> sys.getrefcount(tuple("arbitrary string"))
1
>>> sys.getrefcount(("a", "r", "b", "i", "t", "r", "a", "r", "y", " ", "s", "t", "r", "i", "n", "g"))
2
What is going on here? It seems that immutable types have two references but mutable types have only one? Why does it seem that some objects assigned before being passed, while others only ever have a reference as a parameter?
Does this have something to do with str/int/tuple internment?
Edit: A more directed question: Why was it chosen that immutable types like frozenset() have a reference upon construction, while mutable types like set() does not? I understand in isolation why you might choose to keep this global-scope reference or not across the board, but why the discrepancy?
An interesting question so here is an interesting read.
You should try getrefcount(2), for me it returned 93, which means CPython is keeping 93 references for the same memory address keeping the number two, so it doesn't have to allocate it again and since it is immutable it is totally fine to do it.
Now let's try two different things:
# first
getrefcount(set()) # returns 1
# second
s = set()
getrefcount(s) # returns 2
Since it is mutable types its behavior is different when you create the mutable type (set()) it will allocate it in memory and have only one reference to it which is deleted right after the end of this line. But on the second we define the variable and it allocates it, when counting the references then we have the one used by s and the one used inside the function getrefcount.
And in Python tuples are immutable, this is the reason it returns a huge number, CPython is keeping a lot of references to an empty tuple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With