Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python2.7:使用局部变量作为参数在运行时创建方法_Python_Qt_Python 2.7_Methods_Factory - Fatal编程技术网

Python2.7:使用局部变量作为参数在运行时创建方法

Python2.7:使用局部变量作为参数在运行时创建方法,python,qt,python-2.7,methods,factory,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. I

我的示例使用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>
export  False <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9ec20>
False : 0
创建导出函数:A
创建导出函数:B
然后,如果我按下“B”对应的按钮,控制台将打印:

creating export function:  A <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9e9e0>
creating export function:  B <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9ec20>
export  False <PyQt4.QtGui.QTableWidgetItem object at 0x7fef87c9ec20>
False : 0
导出错误
错:0
所以,如果我期望的是“B”,则打印为“False”。但是请注意,QTableWidgetItem的地址是正确的,因此这种方法似乎是有意义的

使用rapid fix的解决方案会很好,但如果答案也能提供一些关于python如何工作的见解,我会非常高兴

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

这项工作:

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中的某个地方进行管理),因此它可以正常工作


在上面的解决方案中,我确保我指向了一些在保留create之后仍然存在的东西。

为什么要使用嵌套类?你真的需要吗?可能会给您一些解释。@iled我想使用嵌套类向最终用户(包括我自己)隐藏内部构件。通过仅公开导出,我可以自由地以我想要的方式修改字段。话虽如此,为了清楚起见,我应该调用class_字段。您也可以通过继承来实现这一点。我认为这将提高它的可读性和可维护性。一般来说,您的代码很难阅读。避免长行(最多79个字符)并使用更多的空白。给你指引。同样重要的是,考虑到这里难以阅读的张贴代码会吓跑读者(和答案)。不管怎样,很高兴你自己解决了这个问题,并发布了解决方案!