对象继承和嵌套cmd

Rya*_*anN 3 python oop inheritance cmd

这可能是一个基本的面向对象问题:我正在尝试使用 cmd 制作一个嵌套控制台菜单,效果很好。我还希望所有子控制台都可以访问相同的对象。这进展并不顺利。

我的简单例子:

import cmd
class MainConsole(cmd.Cmd):
    def __init__(self,obj1,obj2):
        cmd.Cmd.__init__(self)
        self.prompt = ">"
        self.obj1 = obj1 # The objects I want access to in all my consoles.
        self.obj2 = obj2
        self.menu1 = SubConsole1() # I could pass in the objects here as arguments
        self.menu2 = SubConsole2() # but there should be a better way.

    def do_menu1(self,args):
        self.menu1.cmdloop()
    def do_menu2(self,args):
        self.menu2.cmdloop()
    def do_info(self,args):
        self.menu1.do_info(args)
        self.menu2.do_info(args)
    def do_exit(self,args):
        return -1

class SubConsole1(cmd.Cmd,MainConsole):
    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = "1>"
    def do_action(self,args):
        print self.obj1.someattr1 # Doesn't work

class SubConsole2(cmd.Cmd,MainConsole):
    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = "2>"
    def do_action(self,args):
        print obj1.someattr2 # Doesn't work


class anobject(object):
    def __init__(self,init_value):
        self.someattr1 = init_value
        self.someattr2 = init_value * 2

object1 = anobject(1)
object2 = anobject(2)
c=MainConsole(object1,object2)
c.cmdloop()
Run Code Online (Sandbox Code Playgroud)

当我运行这个时我得到

>
>menu1
1>info
AttributeError: SubConsole1 instance has no attribute 'obj1'
Run Code Online (Sandbox Code Playgroud)

再试一次。

>
>menu2
2>info
NameError: global name 'obj1' is not defined
Run Code Online (Sandbox Code Playgroud)

我不确定 SubConsoles 是否应该是MainConsole. 我还尝试将 SubConsoles 嵌套在MainConsole.

ros*_*dia 5

编辑好的,我误解了你在做什么。

你是对的,SubConsole1和2不需要继承MainConsole。但他们应该有对主控制台的引用。

就像是:

class MainConsole(cmd.Cmd):
    def __init__(self):
       cmd.Cmd.__init__(self, obj1, obj2)
       self.obj1 = obj2
       self.obj2 = obj2

class SubConsole1(cmd.Cmd):
    def __init__(self, maincon):
        cmd.Cmd.__init__(self)
        self.maincon = maincon
Run Code Online (Sandbox Code Playgroud)

self.maincon.obj1然后你可以通过访问和访问你想要的对象self.maincon.obj2

另一种选择(从设计角度来看可能是更好的选择)是将要访问的所有对象提取到 Context 容器对象中,并让所有不同的Cmd对象维护自己对该 Context 容器的引用。

像这样的东西:

import cmd
from collections import namedtuple

class MyConsole(cmd.Cmd):
    def __init__(self, context):
        cmd.Cmd.__init__(self)
        self.context = context

class ConsoleContext(object):
    def __init__(self, **kwargs):
        self.__dict__ = kwargs

class MainConsole(MyConsole):
    def __init__(self, context):
        MyConsole.__init__(self, context)
        self.menu1 = SubConsole1(context)
        self.menu2 = SubConsole2(context)
        self.prompt = '>'

    def do_menu1(self, args):
        self.menu1.cmdloop()

    def do_menu2(self, args):
        self.menu2.cmdloop()

    def do_quit(self, args):
        return True


class SubConsole1(MyConsole):
    def __init__(self, context):
        MyConsole.__init__(self, context)
        self.prompt = '1>'

    def do_action(self, args):
        print self.context.message1

    def do_quit(self, args):
        return True


class SubConsole2(MyConsole):
    def __init__(self, context):
        MyConsole.__init__(self, context)
        self.prompt = '2>'

    def do_action(self, args):
        print self.context.message2

    def do_quit(self, args):
        return True

if __name__ == '__main__':
    context = ConsoleContext(message1='Message 1', message2='Message 2')
    con = MainConsole(context)
    con.cmdloop()
Run Code Online (Sandbox Code Playgroud)

希望我说得足够清楚。