python 2.7:使用locals作为参数在运行时创建方法

时间:2016-01-07 11:23:30

标签: python qt python-2.7 methods factory

我的示例使用QT,但在其他情境中肯定也很有用。

在下面的示例中,Export类的create函数在运行时创建一些函数,作为参数传递局部变量。当按下QT GUI上的按钮时,将调用这些函数:

try:
    from PyQt4 import QtGui,QtCore
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *      
except : raise Exception("failed to import QT. Is it installed ?")
import time,copy

class Export(QTableWidget):

    class Field:

        def __init__(self,name):
            self.name = name

    def __init__(self):
        self.fields = []

    def add(self,name):
        self.fields.append(self.Field(name))

    def create(self,export_function):

        QTableWidget.__init__(self,len(self.fields),3)

        for index,field in enumerate(self.fields):

            self.setItem(index,0,QTableWidgetItem(field.name))
            editable_widget = QTableWidgetItem("0")
            self.setItem(index,1,QTableWidgetItem(editable_widget))

            print "creating export function: ",field.name,editable_widget

            def export(field_name=field.name,widget=editable_widget):
                print "export ",field_name,widget
                value = widget.text()
                export_function(field_name,value)

            export_button = QtGui.QPushButton('set', self)
            export_button.clicked.connect(export)
            self.setCellWidget(index,2,export_button)

class Export_Qt(QMainWindow):

    def __init__(self,parent=None):
        QMainWindow.__init__(self, parent)
        main_widget = QWidget(self)
        layout = QVBoxLayout(main_widget)
        export = Export()
        export.add("A")
        export.add("B")
        def export_function(field,value): print field,":",value
        export.create(export_function)
        layout.addWidget(export)
        main_widget.setLayout(layout)
        self.setCentralWidget(main_widget)        
        self.resize(500,350)


if __name__ == '__main__' :

    app = QApplication([]) 
    main_window = Export_Qt(parent=None)
    main_window.show()
    try:
        while True:
            main_window.update()
            QApplication.processEvents()
            time.sleep(0.05)
    except KeyboardInterrupt: pass
    except Exception as e : print e

让我感到惊讶的是,事情的一半是有效的。将显示GUI,控制台将打印:

creating export function:  A <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9e9e0>
creating export function:  B <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9ec20>

然后,如果我按下对应于“B”的按钮,控制台将打印:

export  False <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9ec20>
False : 0

所以,打印“假”是我期待的“B”。但是请注意QTableWidgetItem的地址是正确的,所以这种方法似乎有意义。

快速修复的解决方案会很棒,但如果答案也提供了一些关于python如何工作的见解,我会非常高兴

注意:我知道只有一个名称属性的类字段没有意义。这是因为上面的代码简化了我正在使用的实际代码。为了便于阅读。

1 个答案:

答案 0 :(得分:0)

这有效:

class Export(QTableWidget):

    class Field:

        def __init__(self,name):
            self.name = name

    def __init__(self):
        self.fields = []
        self.editable_widgets = []

    def add(self,name):
        self.fields.append(self.Field(name))

    def _create(self,field_index,export_function):
        self.setItem(field_index,0,QTableWidgetItem(self.fields[field_index].name))
        editable_widget = QTableWidgetItem("pouet")
        self.editable_widgets.append(editable_widget)
        self.setItem(field_index,1,editable_widget)

        print "creating export function: ",self.fields[field_index].name,editable_widget,editable_widget.text()

        def export():
            print "export ",field_index,self.fields[field_index].name,self.editable_widgets[field_index]
            export_function(self.fields[field_index].name,self.editable_widgets[field_index].text())

        export_button = QtGui.QPushButton('set', self)
        export_button.clicked.connect(export)
        self.setCellWidget(field_index,2,export_button)


    def create(self,export_function):
        QTableWidget.__init__(self,len(self.fields),3)
        for index in range(len(self.fields)):
               self._create(index,export_function)

这是有道理的。离开create函数后,字段不再是有效地址。所以field_name = field.name没有意义。 另一方面,小部件仍然存在(在QT的某个地方管理),因此事情适用于它。

在上面的解决方案中,我确保在指向创建后仍指向仍然存在的内容。