Search code examples
pythonclassvariablespython-2.7dynamic-data

Creating dynamic variables for a class from within the class


For context, I'm working on an inventory system in an RPG, and I'm prototyping it with python code.

What I don't understand is how to make separate variables for each instance of an item without declaring them manually. For a short example:

class Player(object):
    def __init__(self):
        self.Items = {}

class Item(object):
    def __init__(self):
        self.Equipped = 0

class Leather_Pants(Item):
    def __init__(self):
        #What do i place here?
    def Pick_Up(self, owner):
        owner.Items[self.???] = self #What do i then put at "???"
    def Equip(self):
        self.Equipped = 1
PC = Player()
#Below this line is what i want to be able to do
Leather_Pants(NPC) #<-Create a unique instance in an NPC's inventory
Leather_Pants(Treasure_Chest5) #Spawn a unique instance of pants in a treasure chest
Leather_Pants1.Pick_Up(PC) #Place a specific instance of pants into player's inventory
PC.Items[Leather_Pants1].Equip() #Make the PC equip his new leather pants.

If I did something silly in the above code, please point it out.

What I want to do if the code doesn't make it clear is that I want to be able to dynamically create variables for all items as I spawn them, so no two items will share the same variable name which will serve as an identifier for me.

I don't mind if I have to use another class or function for it like "Create_Item(Leather_Pants(), Treasure_Chest3)"

What's the best way to go about this, or if you think I'm doing it all wrong, which way would be more right?


Solution

  • As a general rule, you don't want to create dynamic variables, and you want to keep data out of your variable names.

    Instead of trying to create variables named pants0, pants1, etc., why not just create, say, a single list of all leather pants? Then you just do pants[0], pants[1], etc. And none of the other parts of your code have to know anything about how the pants are being stored. So all of your problems vanish.

    And meanwhile, you probably don't want creating a Leather_Pants to automatically add itself to the global environment. Just assign it normally.

    So:

    pants = []
    pants.append(Leather_Pants(NPC))
    pants.append(Leather_Pants(chests[5]))
    pants[1].pickup(PC)
    

    The pants don't have to know that they're #1. Whenever you call a method on them, they've got a self argument that they can use. And the player's items don't need to map some arbitrary name to each item; just store the items directly in a list or set. Like this:

    class Player(object):
        def __init__(self):
            self.Items = set()
    
    class Item(object):
        def __init__(self):
            self.Equipped = 0
    
    class Leather_Pants(Item):
        def __init__(self):
            pass # there is nothing to do here
        def Pick_Up(self, owner):
            self.owner.Items.add(self)
        def Equip(self):
            self.Equipped = 1