I've created a class called "Test" with attributes "hp" and "max_hp". Now I want to pass these attributes as arguments to an outside function (it is outside the class since I want to use it with other instances of other classes), and add 1 to the attribute if it is not equal to the max attribute. My problem is that even though the function is called and test.hp and test.max_hp passed as arguments, they don't change.
Here's the code:
class Test:
def __init__(self):
self.hp = 10
self.max_hp = self.hp
def recovery_action(attribute, max_attribute):
if attribute == max_attribute:
pass
else:
attribute = 1
test = Test()
test.hp -= 5
print(f'test.hp - {test.hp}')
recovery_action(test.hp, test.max_hp)
print(f'test.hp after recovery - {test.hp}')
The problem is that the output looks like this:
test.hp - 5
test.hp after recovery - 5
I passed the test.hp as an argument and it wasn't equal to test.max_hp, so 1 should have been added to it - but it stayed the same. What am I doing wrong here?
CodePudding user response:
The problem is you are not really changing the attribute in your function.
Basically what you do is call recovery_action(5,10)
.
If you want to actually change the attribute, you can return the result and assign it, like that:
def recovery_action(attribute, max_attribute):
if attribute != max_attribute:
return attribute 1
return attribute
Then you can run:
test.hp = recovery_action(test.hp, test.max_hp)
CodePudding user response:
The variable attribute
lives in the scope of recovery_action
. However, what you would want is to actually reference the class, so that changes are saved outside the scope of the function. A solution could be:
def recovery_action(test: Test):
if test.hp == test.max_hp:
pass
else:
test.hp = 1
This function passes an instance of Test
to the function (hence the : Test
part). The rest of the function is straightforward. Now, you address the variable in the object you pass to the function and thus remains changed after the function ends.
CodePudding user response:
There is no object representing the attribute itself; test.max_hp
is just an expression that evaluates to the value of the attribute. Since an int
is immutable, you can't change the value by passing it as an argument. You would need to pass the object and the name of the attribute as two separate arguments, and have the function operate on the object directly.
def recovery_action(obj, attribute, max_):
if getattr(obj, attribute) == max_:
pass
else:
setattr(obj, attribute, attribute 1)
recovery_action(test, 'hp', test.max_hp)
Note that your function doesn't care that the maximum value comes from an object attribute; it only cares that it is some integer.
CodePudding user response:
Changing the argument of a function will not change the variable you have passed in to that function. You can return the changed variable and reassign the class attribute.
Also maybe creating getter and setter of the attributes is a good idea to access and change attributes of a class.