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.

5 Responses to “python class confusion”

  1. pat Says:

    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’

  2. Ranen Says:

    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.”

  3. Ranen Says:

    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.

  4. Norman Young Says:

    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.

  5. shiftMode » Blog Archive » python class confusion II Says:

    […] 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 […]

Leave a Reply