I have a class in python for a figure with attributes name, health, strength, stealth, agility, weapons and money. There is a shop in the game I'm making to increase the value of any of the integer properties with a specific item. Each integer property can be increased by one of two different items with a different cost and buff strength. The issue I'm having is actually incrementing the attribute by the amount and saving the object.
Here's the code for the object:
class Figure:
def __init__(self, stats):
#create figure object
self.name = stats[0]
self.health = int(stats[1])
self.strength = int(stats[2])
self.stealth = int(stats[3])
self.agility = int(stats[4])
self.weapons = int(stats[5])
self.money = int(stats[6])
def show_person(self):
#show object attributes
print("\n\n{}\n\nHealth: {}\nStrength: {}\nStealth: {}\nCunning: {}\nWeapons: {}\nMoney: £{}".format(self.name.title(),self.health,self.strength,self.stealth,self.cunning,self.weapons, self.money))
def set_attr(self,attr,buff):
#increase character attribute by a variable amount
eval("self.{} = self.{} + {}".format(attr,attr,buff))
I might put friend.set_attr("stealth",10) to increase friend's value of stealth by 10 where friend is a variable that contains one of these Figure objects but this error is thrown:
File Computer Science\python\oop game.py", line 21, in set_attr
exec(eval("self.{} = self.{} + {}".format(attr,attr,buff)))
File "<string>", line 1
self.agility = self.agility + 4
^
SyntaxError: invalid syntax
And I can't work out why.
Assignment is a statement and cannot be used inside an eval, which accepts only expressions. You should use exec instead:
exec("self.{} = self.{} + {}".format(attr,attr,buff))
But instead of exec, it's better to use the setattr function:
setattr(self, attr, getattr(self, attr) + buff)
Don't use exec and eval. Use getattr and setattr:
class Foo:
def __init__(self):
self.x = 0
def set_attr(self, attr, buff):
new_val = getattr(self, attr) + buff
setattr(self, attr, new_val)
foo = Foo()
foo.set_attr('x', 10)
print(foo.x)
# 10
foo.set_attr('x', 11)
print(foo.x)
# 21
Alternatively it is possible to use vars to modify the attribute directly (which personally I tend to like less):
class Foo:
def __init__(self):
self.x = 0
def set_attr(self, attr, buff):
vars(self)[attr] += buff
foo = Foo()
foo.set_attr('x', 10)
print(foo.x)
# 10
foo.set_attr('x', 11)
print(foo.x)
# 21
Just to be clear: you know you could just type
a.foo += 2
If yes, but you need the other method:
Python already has internal functions that does exactly what you're trying to achieve.
The methods are called setattr and getattr. Read more about them here. For now, here's how you can use them:
class A:
b = 3
a = A()
setattr(a, 'b', 5)
print(a.b) # 5
print(getattr(a, 'b')) # 5
setattr(a, 'b', getattr(a, 'b') + 5)
print(a.b) # 10
So you could implement a method that increments an attribute like this:
class A:
def incr_attr(self, attr_name, amount):
setattr(self, attr_name, getattr(self, attr_name) + amount)
Or, even more convenient:
def incr_attrs(self, **attr_map):
for attr_name, amount in attr_map.items():
setattr(self, attr_name, getattr(self, attr_name) + amount)
So you can type
A.incr_attr(stealth=3, money=10)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With