Python, A class within a class,如何从上层class访问变量

Python, A class within a class, how to access variables from the upper class

我有 Qt Gui class 来处理所有变量(p1p2)调整滑块和东西。在这个 class 中,我有一个 OSC 监听器 class,它应该监听触发信号和来自另一个设备的变量 p3,并使用参数触发声音和图形。但是我无法访问监听器 class 中的 p1p2。这是一个例子:

class Ptsgui(QtGui.QMainWindow):
    def __init__(self):
        super(Ptsgui, self).__init__()
        self.p1, self.p2, self.data = 0, 0, np.zeros(10)
        self.initUI()

    class OscListener(object):
        def __init__(self, data):
            self.listenerData = data
            self.receive_address = '127.0.0.1', 7000
        def do_stuff_listener(self, addr, tags, stuff, source):
            print self.p1
            print self.p2
            self.p3 = stuff[0]
            trigger_sound_and_graphic(self.p1, self.p2, self.p3)

        def spawn(self):
            self.receiveServer = OSC.OSCServer(self.receive_address)
            self.receiveServer.addDefaultHandlers()
            self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
            self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
            self.emorating_oscServer.start()

    def initUI():
        """ 
        Some sliders setup for change the p1 & p2
        """
        self.setGeometry(50, 50, 1050, 650)
        mainlayout = QtGui.QVBoxLayout()
        self.widget = QtGui.QWidget()
        self.widget.setLayout(mainlayout)
        self.listener = OscListener(data = self.data)
        self.show()

所以在这里我希望 oscListener() 可以直接访问 self.p1self.p2。显然我不能这样做,因为 self.p1 的 'self' 指的是 OscListener 而不是 Ptsgui。另外 do_stuff_listener 在一个单独的线程中,是否仍然可以访问 self.p1self.p2

最终,我希望用户可以通过GUI来控制参数值。并且每次通过 OSC 接收到触发信号时,它都会生成新的图形和声音。如果有更好的方法,请提出建议。

您可以像这样将Ptsgui传递给OscListener

class Ptsgui(QtGui.QMainWindow):
    def __init__(self):
        super(Ptsgui, self).__init__()
        self.p1, self.p2, self.data = 0, 0, np.zeros(10)
        self.initUI()

    class OscListener(object):
        def __init__(self, cls, data):
            self.parent = cls
            self.listenerData = data
            self.receive_address = '127.0.0.1', 7000
        def do_stuff_listener(self, addr, tags, stuff, source):
            print self.parent.p1 # Access it.
            print self.parent.p2
            self.p3 = stuff[0]
            trigger_sound_and_graphic(self.p1, self.p2, self.p3)

        def spawn(self):
            self.receiveServer = OSC.OSCServer(self.receive_address)
            self.receiveServer.addDefaultHandlers()
            self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
            self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
            self.emorating_oscServer.start()

    def initUI():
        """ 
        Some sliders setup for change the p1 & p2
        """
        self.setGeometry(50, 50, 1050, 650)
        mainlayout = QtGui.QVBoxLayout()
        self.widget = QtGui.QWidget()
        self.widget.setLayout(mainlayout)
        self.listener = OscListener(cls=self, data = self.data) # Pass it here
        self.show()

你想要达到的目标可以这样实现:

class Ptsgui(QtGui.QMainWindow):
    def __init__(self):
        super(Ptsgui, self).__init__()
        self.p1, self.p2, self.data = 0, 0, np.zeros(10)
        self.initUI()

    def initUI():
        """
        Some sliders setup for change the p1 & p2
        """
        self.setGeometry(50, 50, 1050, 650)
        mainlayout = QtGui.QVBoxLayout()
        self.widget = QtGui.QWidget()
        self.widget.setLayout(mainlayout)
        self.listener = OscListener(gui=self, data=self.data)
        self.show()


class OscListener(object):
    def __init__(self, gui, data):
        self.gui = gui
        self.listenerData = data
        self.receive_address = '127.0.0.1', 7000
    def do_stuff_listener(self, addr, tags, stuff, source):
        print self.gui.p1
        print self.gui.p2
        self.p3 = stuff[0]
        trigger_sound_and_graphic(self.gui.p1, self.gui.p2, self.gui.p3)

    def spawn(self):
        self.receiveServer = OSC.OSCServer(self.receive_address)
        self.receiveServer.addDefaultHandlers()
        self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
        self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
        self.emorating_oscServer.start()

发现不需要代码示例中的 class 嵌套。

另外,在我看来,你想要达到的目标是不对的。代码非常耦合。考虑解耦 PtsguiOscListener。检查 Observer pattern 以获得一些灵感。