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