Question

I'm getting what seems to be curious behavior in python. I can't figure out if it's a quirk or that I've done something wrong. Why is passing in an object's self.var as an argument to one of its methods does not allow me to assign the self.var that has been initialized?

class Test():
    def __init__(self):
        self.num1 = 0
        self.num2 = 0

    def selfexp(self, n, metric):
        result = n ** n
        metric = result
        print metric

a = Test()

a.selfexp(2, a.num1)
a.selfexp(5, a.num2)

print a.num1
print a.num2

Output:

4
3125
0 # expected 4
0 # expected 3125
Was it helpful?

Solution

metric is just a local variable, and it is not a reference to the attribute. When you call a function or a method, python passes in the referenced object. That means the value referenced by a.num1 or a.num2 is passed in, not an attribute. In your example, metric is 0 in both cases because the result of the expressions a.num1 and a.num2 is both 0.

If you wanted to tell a method what attribute to assign to, use setattr() and pass in a string:

def selfexp(self, n, metric):
    result = n ** n
    setattr(self, metric, result)
    print getattr(self, metric)

and:

a.selfexp(2, 'num1')

I used the getattr() function to read the same named attribute again as well.

OTHER TIPS

When you call selfexp, metric is just a reference to the same integer object as a.num1. Assigning a new value to metric inside the method just changes what the name metric points to; it does not change the object that a.num1 points to.

Ned Batchelder has a nice blog post that explains the semantics of names and values in Python.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top