python call-by-reference on primitive types
I have experience with the imperative languages(C most often), and that's probably why I am confused in learning python.
I am trying to implement a simple bitwise flag-setter functions. So in C it would be like:
void set_state(int *state, int var, int set)
{
(set)? *state |= var : *state &= ~var
}
int is_state(int *state, int var)
{
return (*state & var > 0)
}
int *state refers to a state flag that I keep track of, and var is the flag that I would like to set or clear(decided by int set).
So I tried to 开发者_如何转开发do the same with Python 3.2 and...
def setState(nState, nVar, bSet):
if bSet:
nState |= nVar
else:
nState &= ~var
print(nState)
Then I ran...
>>> state
1024
>>> nfirst
1
>>> nsecond
2
>>> setState(state, nfirst, True)
1025
>>> state
1024
debugger tells me that the value of 'state' got copied into nState and now nState got mutated itself(meaning it was changed in its own local scope). Wasn't python all about objects and everything-is-call-by-reference?
If so, why can't I see a side effect?
I am lost. Can someone explain what is going on here.
Python int
s are immutable, so while a reference is being passed in, it is not possible to change the value of the int object. As you have seen, the local variable is a copy of the reference, so they are both bound to the same integer. However when you change the value of the local variable, a new integer object is created, and the local variable is rebound to the new object.
eg.
>>> def setState(nState, nVar, bSet):
... print((nState, id(nState)))
... if bSet:
... nState |= nVar
... else:
... nState &= ~var
... print((nState, id(nState)))
...
>>> nState = 1024
>>> nState, id(nState)
(1024, 3077840368)
>>> setState(nState, 1, True)
(1024, 3077840368) # local nState is bound to the same object
(1025, 3077840448) # now the local nState is bound to the new `int` object
perhaps you can return nState from the function and assign it back, eg
>>> def setState(nState, nVar, bSet):
... if bSet:
... nState |= nVar
... else:
... nState &= ~var
... return nState
...
>>> nState = 1024
>>> nState = setState(nState, 1, True)
>>> nState
1025
Primitive types like numbers or strings aren't mutable, you cannot change a number even if it were passed by reference. When you changed the value you actually created a new number and assigned the reference to it to the nState
variable.
http://mail.python.org/pipermail/tutor/2002-November/018828.html pretty much answers your question.
We can think of all "variable names" in Python as pointers to objects. In fact, that's pretty much what's going on.
[...]
The key here is that arithmetic in Python (or any manipulation on an "immutable" data type), does not modify the object, though: it dynamically constructs new objects:
Since lists, dicts and custom objects are usually mutable calling methods on them will not create a new object but modify the existing one, so you have the call-by-reference behaviour for those types you might actually expect.
精彩评论