The reference count of list1
and list2
doesn't change, they are just variables and thus string keys in a locals()
namespace.
The Python list objects that these two variables point to, though, yes, their reference count changes when passed to a function. During the call to the function two new variables refer to those lists (l1
and l2
) increasing the count, and when the function returns those variables are cleaned up and the ref count goes down again.
Inside the calculate()
function, you are accessing items of these two lists (l1[0]
, etc.). Item access could use the __getitem__
method of objects; methods are created on-the-fly when accessed, and hold a reference to the instance and the underlying function. For a list that is another reference to the list object, and another temporary reference count increase. Once the function has been called and returned it's value, the method is discarded again (nothing is referencing it) and the ref count for the list drops again.
As delnan rightly points out in the comments, for list subscription the BINARY_SUBSCR
opcode optimizes access (provided the index is an integer) and no method is created in that specific case.
The python interpreter, when handling bytecode and values on the stack, is increasing and decreasing reference counts all the time though. Take a look through the Python bytecode evaluation loop and count the number of Py_INCREF
and Py_DECREF
occurrences to to get an idea of how common this is.