Ikke
Ikke

Reputation: 101221

Python reference problem

I'm experiencing a (for me) very weird problem in Python.

I have a class called Menu: (snippet)

class Menu:
    """Shows a menu with the defined items"""
    menu_items = {}
    characters = map(chr, range(97, 123))

    def __init__(self, menu_items):
        self.init_menu(menu_items)

    def init_menu(self, menu_items):
        i = 0
        for item in menu_items:
            self.menu_items[self.characters[i]] = item
            i += 1

When I instantiate the class, I pass in a list of dictionaries. The dictionaries are created with this function:

def menu_item(description, action=None):
    if action == None:
        action = lambda : None
    return {"description": description, "action": action}

And then the lists are created like this:

t = [menu_item("abcd")]
m3 = menu.Menu(t)

a = [ menu_item("Test")]
m2 = menu.Menu(a)

b = [   menu_item("Update", m2.getAction),
                      menu_item("Add"),
                      menu_item("Delete")]
m = menu.Menu(b)

When I run my program, I everytime get the same menu items. I've run the program with PDB and found out as soon as another instance of a class is created, the menu_items of all previous classes are set to latest list. It seems as if the menu_items member is static member.

What am I overseeing here?

Upvotes: 3

Views: 349

Answers (2)

Jochen Ritzel
Jochen Ritzel

Reputation: 107598

Since Pär answered your question here is some random advice: dict and zip are extremely useful functions :-)

class Menu:
    """Shows a menu with the defined items"""
    characters = map(chr, range(97, 123))

    def __init__(self, menu_items):
        self.menu_items = dict(zip(self.characters, menu_items))

Upvotes: 5

Pär Wieslander
Pär Wieslander

Reputation: 28934

The menu_items dict is a class attribute that's shared between all Menu instances. Initialize it like this instead, and you should be fine:

class Menu:
    """Shows a menu with the defined items"""
    characters = map(chr, range(97, 123))

    def __init__(self, menu_items):
        self.menu_items = {}
        self.init_menu(menu_items)

    [...]

Have a look at the Python tutorial section on classes for a more thorough discussion about the difference between class attributes and instance attributes.

Upvotes: 16

Related Questions