python class confusion
February 18th, 2008[ Geek ]
I’m sure this is explained quite clearly somewhere like here or here. Hopefully someday I’ll be pythonic enough to understand. In the meantime, this is confusing to me and a bit scary. I’m hoping someone can explain to me why I’d want this behaviour.
Let’s take a really simple class with one method. All that method does is creates a variable local to that method and then print it out. One catch, first I call a second method, passing in that variable, and change it within the scope of that second method. As expected, that has no impact on the variable in the calling method and the result when you run it is “local…”
class klass(object):
def settime(self, s):
s=’remote’
def dosomething(self):
astring=’local’
self.settime(astring)
print “%s…” % astring
if __name__ == “__main__”:
c = klass()
c.dosomething()
Modify the above, adding a class within that same method call, again attempting to modify it in the second method call. Again, do nothing more than print both variables out. My instincts do NOT have me expecting the results I get, which are “local remote…”
class me(object):
def __init__(self, n):
self.name=n
class klass(object):
def settime(self, t, s):
t.name=’remote’
s=’remote’
def dosomething(self):
astring=’local’
aclass=me(’local’)
self.settime(aclass, astring)
print “%s %s…” % (astring, aclass.name)
if __name__ == “__main__”:
c = klass()
c.dosomething()
No, these aren’t my typical naming conventions.
February 20th, 2008 at 9:40 pm
makes sense to me (i think), the string (s) gets passed by value and the object (t) gets passed by reference - there’s only one ‘me’
February 20th, 2008 at 11:48 pm
Hi Brydon.
I found this helpful:
http://www.goldb.org/goldblog/CommentView,guid,4eb92070-c279-44b3-ac2a-5d1c4f3e8115.aspx
“In Python every variable assignment (even an assignment of a small integer) is an assignment of a reference. Every function call involves passing the values of those references.”
and
“It is important to understand mutable and immutable objects. Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed. Other objects, like lists and dictionaries are mutable, which means you can change the object in-place. Therefore, altering an object inside a function/method will also change the original object outside.”
February 21st, 2008 at 12:07 am
Hi Brydon.
I found this helpful: http://www.goldb.org/goldblog/CommentView,guid,4eb92070-c279-44b3-ac2a-5d1c4f3e8115.aspx
“Alex is right that trying to shoehorn Python into a “pass-by-reference” or “pass-by-value” paradigm is misleading and probably not very helpful. In Python every variable assignment (even an assignment of a small integer) is an assignment of a reference. Every function call involves passing the values of those references.”
and
It is important to understand mutable and immutable objects. Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed. Other objects, like lists and dictionaries are mutable, which means you can change the object in-place. Therefore, altering an object inside a function/method will also change the original object outside.
February 21st, 2008 at 12:23 pm
Short answer:
t.name=”remote” alters the “t” object’s “name” attribute, whereas s=”remote” alters only the local s variable. The astring variable remains unchanged.
Long answer:
All variables (including functions’ parameters) are references to objects. Assigning a variable merely changes the object to which the variable refers.
Modules, classes and functions are objects which, when nested, define hierarchies of namespaces. The . dot notation dereferences each level within the hierarchy by implicitly querying the object’s attributes __dict__ using the key . The result of dereferencing is always an object.
At the line
t.name=’remote’
in the example, “t” is a local variable (i.e., an implicit attribute of the “settime” method function object) referencing a passed-in object. The assignment sets that passed-in object’s “name” attribute to reference the local string object “remote”. (Note that this assignment occurs independently of whether or not the passed-in object had a “name” attribute previously. In this case, it did, but that fact is immaterial to the printed outcome.)
Before the execution of the line
s = “remote”
“s” is a local variable which references the passed-in string object “local”. After execution, the “s” variable references the local string object, “remote”. Upon termination of the enclosing method function, the “s” variable falls out-of-scope and the “remote” string object gets garbage-collected.
February 21st, 2008 at 10:20 pm
[…] am I’m glad I’m dumb. Seriously, I really need to ask more stupid questions here if these are the returns I’m going to […]