Kay Dee
Kay Dee

Reputation: 43

Creating instance names from a list (Python)

I've got a function that builds a random number of object instances. For the sake of demonstrating the general idea, we're going to pretend that this is an algorithm to build a series of nethack-like rooms.

The requirements are such that I won't know how many instances there will be in advance; these are generated randomly and on-the-fly.

As a brief note: I am fully aware that the following code is nonfunctional, but it should (hopefully!) demonstrate my aims.

import random

class Levelbuild(object):

    def __init__(self):
        self.l1 = dict({0:'a',1:'b',2:'c',3:'d',4:'e',5:'f',6:'g',7:'h',8:'i'})
        # Pick a random number between 4 and 9.
        for i in range(random.randint(4,9)):
            self.l1[i] = Roombuilder()

If we assume that the chosen random integer is 5, the ideal result would be 5 Roombuilder() instances; labeled a, b, c, d, and e, respectively.

Is there a simple way of doing this? Is there a way to do this period?

--Edit--

A giant "thank you" to Nick ODell for his answer. This isn't a complete copy/paste-- but it's a variation that works for what I need;

import random

class Room(object):
    def __init__(self):
        self.size = (5,5)

class Level(object):

    def __init__(self):
        roomnames = ['a','b','c','d','e','f','g','h','i']
        self.rooms = {}
        for i in range(random.randint(4, 9)):
            self.rooms[roomnames[i]] = Room()

Rather than build each "room" by hand, I can now...

test = Level()
print test.rooms['a'].size
>>> (5,5)

Upvotes: 3

Views: 672

Answers (3)

Gareth Latty
Gareth Latty

Reputation: 88987

As another answer for a more general solution (mainly as a companion to Nick ODell's answer, if you want to handle any number of names, it's a pretty simply solution with an infinite generator:

import string
import itertools

def generate_names(characters):
    for i in itertools.count(1):
        for name in itertools.product(characters, repeat=i):
            yield "".join(name)

You can then use it as you would any other generator:

>>>print(dict(zip(generate_names(string.ascii_lowercase), range(30))))
{'aa': 26, 'ac': 28, 'ab': 27, 'ad': 29, 'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18, 'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}

If you need to generate actual names, then you have a few choices. If you need a real word, pick from a dictionary file (most Linux users have one in /usr/share/dict). If you need word-like things, then I have actually written a Python script to generate such 'words' using Markov Chains, which is available under the GPL. Naturally, you'd have to check these for uniqueness.

Upvotes: 0

Nick ODell
Nick ODell

Reputation: 25220

import string
import random

class Levelbuild(object):

  def __init__(self,min_room_count,max_room_count):

    rooms_temp = [new RoomBuilder() for i in range(random.randint(min_room_count,max_room_count))]
    self.l1 = dict(zip(string.ascii_lowercase, rooms_temp))

Note: This will fail silently if given more than 26 rooms.

Upvotes: 3

Eevee
Eevee

Reputation: 48546

You're pretty close, actually. You don't need a dict; just use a list. (And, by the way, {...} is already a dict, so wrapping it in dict() doesn't do anything.)

roomnames = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
self.rooms = []
for i in range(random.randint(4, 9)):
    self.rooms.append(Roombuilder(roomnames[i]))

For what it's worth, putting builder in the name of a class is kind of funky. The objects are rooms, right? So the type should just be Room.

Upvotes: 0

Related Questions