【问题标题】:Python reference problemPython参考问题
【发布时间】:2009-12-08 13:44:19
【问题描述】:

我在 Python 中遇到了一个(对我而言)非常奇怪的问题。

我有一个类叫 Menu: (sn-p)

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

当我实例化这个类时,我传入了一个字典列表。字典是用这个函数创建的:

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

然后列表是这样创建的:

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)

当我运行我的程序时,我每次都会得到相同的菜单项。我已经用 PDB 运行了这个程序,发现一旦创建了一个类的另一个实例,所有以前的类的 menu_items 都设置为最新列表。似乎 menu_items 成员是静态成员。

我在这里监督什么?

【问题讨论】:

    标签: python reference


    【解决方案1】:

    menu_items dict 是一个在所有Menu 实例之间共享的类属性。像这样初始化它,你应该没问题:

    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)
    
        [...]
    

    查看Python tutorial section on classes 以更深入地讨论类属性和实例属性之间的区别。

    【讨论】:

    • 以这种方式共享它们的原因是什么?
    • 不,这是因为您将menu_items 定义为类属性(直接在class Menu 中)而不是作为实例属性(在类的方法中初始化)。
    • 它以这种方式工作的原因(很像其他语言中的静态属性)是您有时希望能够在实例之间共享数据。我在答案中添加了指向 Python 教程的链接,您可以在其中阅读有关类和实例属性如何工作的更多信息。
    • 好吧,我错误地认为那些是实例成员,但它们是类成员。
    【解决方案2】:

    既然 Pär 在这里回答了您的问题,这里有一些随机建议:dictzip 是非常有用的函数 :-)

    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))
    

    【讨论】:

    • 谢谢,我忘了zip功能了。
    猜你喜欢
    • 1970-01-01
    • 2014-10-03
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 1970-01-01
    相关资源
    最近更新 更多