2

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.

Splurk
  • 711
  • 1
  • 5
  • 15

4 Answers4

7

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()
RichieHindle
  • 272,464
  • 47
  • 358
  • 399
5

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()
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Thanks for your feedback! I ended up using the Richie's solution, but I can definitely see the advantages to this approach as well. I will most likely end up using some of this as well. Thank you! – Splurk May 16 '13 at 09:04
1

You have three options:

  1. Use eval: eval(monster_instance + ' = Monster()'). eval basically executes a string. Note that, as RichieHindle said in the comments, eval isn't an ideal solution. It may be an option, but that doesn't mean it is recommended.

  2. Use an array/list: monsters.append(Monster()). Initialize it using monsters = [].

  3. Use a dictionary: monsters[monster_instance: Monster()] or monsters.update({monster_instance: Monster()}). Initialize it using monsters = dict().

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
  • 3
    Please don't encourage newbies to use `eval` or `exec`. It's rarely the right answer. – RichieHindle May 15 '13 at 22:28
  • 1
    I actually found eval when initially researching this, but luckily most posts said that I should stay away from that for now. But thanks for the input :-) – Splurk May 16 '13 at 09:06
0

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.

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • It is possible to create dinamic classes in Python [using metaclasses](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python) – Saullo G. P. Castro May 15 '13 at 22:45
  • @SaulloCastro (a) it is possible to create dynamic classes without using metaclasses (b) neither the question nor answer discusses dynamic classes, so I don't understand the point of your comment. – Marcin May 15 '13 at 22:49
  • I thought the problem could be solved with dynamic classes. When I read your answer I disagreed in the point is says you can't create instances of a class without knowing the name of the instance pre runtime. But now I believe I got your point... the name of the instance must be known beforehand, I understood "the name of the classes"... – Saullo G. P. Castro May 15 '13 at 22:57
  • I see now that I dont need to provide a name to create an instance of something. I thought I needed that to create an instance, which is why I wanted to create the names dynamically. From Blckknght's solution I saw that i could just do 'monsters.append(Monster())' to create an instance. Thanks for your input :-) – Splurk May 16 '13 at 09:11