I'm quite new to Python and programming in general.
I'm making a terminal based game as a practice project. The game will a series of rooms and monsters. My plan was to make monsters and rooms instances of these classes. I'm creating several of these throughout the game and many of them a created on the fly, based on player actions.
When creating new monsters and rooms, i'm currently stuck to knowing their names beforehand. like so:
class Monster(object):
pass
Monster1 = Monster(something)
Having to know the instance name pre runtime seems like a clumsy solution. I was thinking it would be easier to have a variable keep track of the number of monsters, and then dynamically create the instance names. So that the first monster instance created would automaticallt be Monster1, the next would be Monster2 etc.
Something like this:
class Monster(object):
pass
monster_id = 0
def createMonster(monster_id)
monster_instance = "Monster" + str(monster_id)
monster_id += 1
# The following is where i'm stuck. Basically I want to have the instance name be equal to the content of monster_instance
(monster_instance) = Monster()
So the questions is: How can I create instances of a class without knowing the name of the instance pre runtime?
I'm also wondering if I'm having a hard time getting this to work, because I'm doing something stupid and that is a much smarter/elegant way of doing this. All help and input is much appreciated under all circumstances.
4 Answers 4
This is a common question from newbies, and you're right, there is a "much smarter/elegant way of doing this". You use a data structure like a dictionary to hold your instances:
monsters = {}
monsters['Monster1'] = Monster()
monsters['Monster2'] = Monster()
Because the keys to the dictionary are strings, there's no problem defining them at runtime however you like:
monster_name = "Monster" + str(monster_id)
monster_id += 1
monsters[monster_name] = Monster()
Comments
I'm pretty sure you don't really want to do what you're asking how to do.
Instead of creating dynamic names (which you won't be able to use later, since you won't know their names), you should use a data structure to hold your objects. For instance, a list can be easily indexed by an integer, so your monster1 variable can become monsters[1]:
# create the list of monsters
monsters = [Monster(1), Monster(2), Monster(3)] # or whatever parameters
# then later, use it
monster[1].eat_player()
Or rather than setting up the whole list ahead of time and using explicit indexing, you could make the list dynamic and iterate over it:
# setup
monsters = [] # empty list
# later, dynamically add monsters
monster_spawn_timer -= 1
if monster_spawn_timer < 0:
monster_spawn_timer += MONSTER_SPAWN_INTERVAL
monsters.append(Monster())
# and at some other point in your main loop, you can iterate over the monsters:
for m in monsters:
m.do_stuff()
1 Comment
You have three options:
Use
eval:eval(monster_instance + ' = Monster()'). eval basically executes a string. Note that, as RichieHindle said in the comments,evalisn't an ideal solution. It may be an option, but that doesn't mean it is recommended.Use an array/list:
monsters.append(Monster()). Initialize it usingmonsters = [].Use a dictionary:
monsters[monster_instance: Monster()]ormonsters.update({monster_instance: Monster()}). Initialize it usingmonsters = dict().
2 Comments
eval or exec. It's rarely the right answer.So the questions is: How can I create instances of a class without knowing the name of the instance pre runtime?
You don't. You are confused.
You only create instances at runtime, and you do not want to encode any information about the object in its variable name, because your programme will not interact with the variable name.
You use datastructures to keep track of your objects. If they need to have a unique id, the best solution is to assign a UUID on object creation.