简体   繁体   中英

How to assign a class variable “dynamically” in Python?

I have the following code :

class Potion(object):
    def __init__(self,name,var,varamount):
        self.name=name
        self.var=var
        self.varamount=varamount

class Inventory(object):
    def __init__(self):
        self.items={}
    def use_potion(self,potion):
        potion.var+=potion.varamount
        print("Used a ",potion.name," !")

class Player():
    def __init__(self):
        self.health=100
        self.mana=100
        self.stamina=100

inventory=Inventory()
player=Player()
healthpotion=Potion("Health potion",player.health,50)
inventory.use_potion(healthpotion)

Here, my health potion is supposed to add 50 to the variable player.health . But player.health remains unchanged, only healthpotion.var is changed. Assuming I want different types of potions (stamina, mana, health), how can I dynamically assign player.health , player.stamina and player.mana to potion.var ?

这样做不起作用的原因是您已经将参数player.health传递给了Potion,这与编写相同:

Potion("Health potion",100,50)
class Potion():
    def __init__(self,name,var,varamount):
        self.name=name
        self.var=var
        self.varamount=varamount

class Inventory():
    def __init__(self):
        self.items={}

    def add_item(self, item):
        if item in self.items.keys():
            self.items[item] += 1
        else:
            self.items[item] = 1
        print ('Added a {} potion!'.format(item.name)

    def remove_item(self, item):
        if item in self.items.keys():
            self.items[item] -= 1
            return True
        else:
            print ('No such {} exists!'.format(item.name))
            return False


class Player():
    def __init__(self):
        self.health=100
        self.mana=100
        self.stamina=100
        self.inventory = Inventory()

    def use_item(self, item):
        if isinstance(item, Potion):
            if self.inventory.remove_item(item):
                if item.var == 'health':
                    self.health += item.varamount
                    print ('Used a {0} and healed {1}!'.format(item.name, item.varamount))

player=Player()
healthpotion=Potion("Health potion", 'health', 50)
player.use_item(healthpotion)
player.inventory.add_item(healthpotion)
player.use_item(healthpotion)

#No such Health potion exists!
#Added a health potion!
#Used a Health potion and healed 50!

You need to think through the way your objects work first.

Does the inventory use the potion, or does the player use the potion?

In the code I provided, I made Player class have its own inventory. And then Player can use potion that was added into its own inventory.

You need to send created instance of Player , not just value of their attribute:

class Potion(object):
    def __init__(self,name,var,varamount):
        self.name=name
        self.var=var
        self.varamount=varamount

class Inventory(object):
    def __init__(self):
        self.items={}
    def use_potion(self,potion):
        # Your potion.var contains Player instance. Access players health.
        potion.var.health += potion.varamount
        print("Used a ",potion.name," !")

class Player():
    def __init__(self):
        self.health=100
        self.mana=100
        self.stamina=100

inventory=Inventory()
player=Player()
healthpotion=Potion("Health potion",player,50) # Send player instance.
print(player.health) # 100
inventory.use_potion(healthpotion)
print(player.health) # 150

You using objects. Objects 'know' things - the values of their attibutes - and objects can send messages to each other - by calling their methods.

In this case:

  • Player knows their health.
  • Potion knows how much it can increase health by
  • Inventory knows whether or not the it has a potion.
  • Player should have an inventory
  • Player can choose to use items in its inventory
  • Inventory keeps track of whether an item has been used

Based on these facts, we know which methods and attributes our classes need.

Potion needs to know how many health points it can restore

class Potion(object):

    def __init__(self,name, varamount):
        self.name=name
        self.varamount=varamount

Inventory needs to be able to keep track of its contents.

class Inventory(object):
    def __init__(self):
        self.items={}

    def add_potion(self, potion):
        self.items['potion'] = potion

    def get_potion(self):
         return self.items.get('potion')

    def remove_potion(self):
        self.items.pop('potion', None)

Player needs to be able to track its health, and use potions.

class Player():
    def __init__(self, inventory):
        self.health=100
        self.mana=100
        self.stamina=100
        self.inventory = inventory

    def use_potion(self):
        potion = self.inventory.get_potion()
        if potion:
            self.health += potion.varamount
            self.inventory.remove_potion()
        print("Used a ",potion.name," !")

inventory=Inventory()

healthpotion=Potion("Health potion", 50)
inventory.add_potion(healthpotion)

player=Player(inventory)
player.use_potion()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM