I am trying to use a method defined in a class to later modify an attribute of an object made from that class, but there appears to be a scope problem that is not obvious to me. Take the following code:
class Test:
def __init__(self, attribute):
self.attribute = attribute
def change_attrib(self, attribute, value):
if attribute + value < 0: attribute = 0
else:
attribute += value
print(str(attribute) + ' This is inside the method')
test1 = Test(10)
print(str(test1.attribute) + " This is before running the method")
test1.change_attrib(test1.attribute, 10)
print(str(test1.attribute) + " This is after running the method")
test1.attribute += 20
print(str(test1.attribute) + " This is after modifying the attribute directly")
Running this code produces the following result:
10 This is before running the method
20 This is inside the method
10 This is after running the method
30 This is after modifying the attribute directly
So it appears that even though I am explicitly referring to the instance that I want to change when calling the method, everything that happens in the method, stays in the method.
I can see that modifying the attribute directly works, but I would like a guard against negative values (hence the method). I also know I can use the built-in setattr() function within the method, and that works as well, but requires that I change the syntax for the attribute to a string before passing it into the method, and I much prefer explicitly referring to the attribute. Finally, I'd really just like to understand what is going on here.
EDIT: This is the working code, based on the hint from rdvdev2. I just needed to reference self to set the instance's value:
class Test:
def __init__(self, attribute):
self.attribute = attribute
def change_attrib(self, attribute, value):
if attribute + value < 0: attribute = 0
else:
attribute += value
self.attribute = attribute
print(str(attribute) + ' This is inside the method')
Also thanks to kindall for the great explanation of what was happening.
And a final expansion: The code above actually only works if the attribute is named attribute. I think kindall had the better grasp of what I needed here; in order for the function to be used to modify any attribute of the object, I need some way to reference the needed attribute. Since python appears to be passing a value instead of a reference, I have to get the reference somehow, and the least impactful way to my existing code appears to be using get/setattr....so I broke out regex and changed 160+ references.