从 QMainWindow 调用具有变量名的 Python 函数

Posted

技术标签:

【中文标题】从 QMainWindow 调用具有变量名的 Python 函数【英文标题】:Call a Python function with a variable name from a QMainWindow 【发布时间】:2021-05-28 09:43:37 【问题描述】:

我正在尝试找到一种有效且安全的方法来根据用户输入的交易名称调用不同的函数。有 100 多种不同的交易。 100“IF”可以完成这项工作,但是,我想找到一种更有效的方式来调用事务。 “eval”会这样做,但我读到不应该使用它,因为用户可以输入任何事务名称。

from operator import methodcaller
import  sys
from    PyQt5.QtWidgets     import (QMainWindow,QToolBar,QLineEdit,
                                    QLabel, QApplication)
def one():
        print ("1")

def two():
        print ("2")

def three():
        print("3")

class main_menu(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        menuBar = self.menuBar()
        self.ToolBar = QToolBar()
        self.ToolBar.setMovable(False)
        self.addToolBar(self.ToolBar)
        self.tcode = QLineEdit(maxLength=5)
        self.tcode.returnPressed.connect(self.tcode_action) 
        self.ToolBar.addWidget(QLabel("  Transaction : "))
        self.ToolBar.addWidget(self.tcode)

    def tcode_action(self):
##        if self.tcode.text() == "one":
##                one()
##        if self.tcode.text() == "two":
##                two()
##        if self.tcode.text() == "three":
##                three()

##        eval(self.tcode.text()+"()")        

def main(args):
    app                 = QApplication(sys.argv)
    mm = main_menu()
    mm.show()
    sys.exit(app.exec_())
if __name__=="__main__":
    main(sys.argv)


【问题讨论】:

附注,因为 Anurag Regmi 已经回答了这个问题:始终使用 if --> elif --> else 和大量 if 。如果你不这样做,即使在 if 已经匹配之后,它也会执行其余的 ifs... 【参考方案1】:

可以通过python中的globals()访问全局变量。 您可以使用:

def tcode_action(self):
    fn = globals().get(self.tcode.text())
    if fn:
        fn()
    else:
        print("invalid input")

【讨论】:

注意,使用它有一些危险,因为它可能会导致任意代码执行(例如,用户输入main)。更安全的方法是使用this example 中所示的字典,但如果有 100 多个不同的函数可以调用,那可能会很痛苦......【参考方案2】:

一种选择是使用QComboBox 来限制功能集。您还可以使用Enum 枚举有效函数。

from enum import Enum
from functools import partial


# function definitions
def fcn_1( x ):
  print( 'F1' )


def fcn_2( x ):
  print( 'F2' )


# valid functions Enum
# Must wrap functions in partial so they are not defined as methods.
# See below post for more details.
class ValidFunctions( Enum ):
  Echo = partial( fcn_1 )
  Increment = partial( fcn_2 )


# function selection ComboBox
cb = QComboBox()
cb.addItem( 'Echo' )
cb.AddItem( 'Increment' )


# connecting the signal
def call_function():
  fcn = ValidFunctions[ cb.currentText() ]
  fcn()


cb.currentIndexChanged.connect( call_function )

注意:我没有调试过这段代码。

How to define enum values that are functions

【讨论】:

【参考方案3】:

我现在将使用此代码执行此操作:

def tcode_action(self):
    try:
            func = getattr(self,self.tcode.text())
            func()
    except:
            pass

对此有什么办法吗?

【讨论】:

在您的原始代码中,函数不是该类的成员,因此调用 getattr 将不起作用,您应该使用全局变量使用 @Anurag Regmi 的代码,或者将您的函数移动为您的成员类。 对,我把函数移到类了。

以上是关于从 QMainWindow 调用具有变量名的 Python 函数的主要内容,如果未能解决你的问题,请参考以下文章

py 5.11

获取具有两个变量和多个行名的 p 值

week2 作业

如何从另一个类调用 QMainWindow 组件?

从 QWidget (PyQt4) 调用 QMainWindow 中的方法/属性

如何附加多个具有相同变量名的 .mat 文件?