使用字典选择要执行的函数

99 投票
12 回答
193931 浏览
提问于 2025-04-17 12:27

我想用函数式编程来创建一个字典,这个字典里包含一个键和一个要执行的函数:

myDict={}
myItems=("P1","P2","P3",...."Pn")
def myMain(key):
    def ExecP1():
        pass
    def ExecP2():
        pass
    def ExecP3():
        pass
        ...
    def ExecPn():
        pass  

我看到过一些代码可以用来查找模块中定义的函数,我需要做类似的事情:

    for myitem in myItems:
        myDict[myitem] = ??? #to dynamically find the corresponding function

所以我的问题是,我该如何列出所有的 Exec 函数,然后用字典把它们分配给想要的项目?这样最后我就能通过 myDict["P1"]() #这会调用 ExecP1() 来执行了。

我真正的问题是,我有很多这样的项目,我正在制作一个库来处理它们,这样最终用户只需要调用 myMain("P1") 就可以了。

我觉得可以使用 inspect 模块,但我不太确定该怎么做。

我想避免的原因是:

def ExecPn():
    pass
myDict["Pn"]=ExecPn

因为我需要保护代码,因为我在我的应用程序中使用它来提供脚本功能。

12 个回答

32

这段话的意思是:要简化你的代码,尽量让它简单易懂。同时,遵循“不要重复自己”(DRY)的原则,也就是在写代码的时候,尽量避免重复相同的内容。这样可以让代码更清晰,也更容易维护。

tasks = {}
task = lambda f: tasks.setdefault(f.__name__, f)

@task
def p1():
    whatever

@task
def p2():
    whatever

def my_main(key):
    tasks[key]()
207

简化,简化,再简化:

def p1(args):
    whatever

def p2(more args):
    whatever

myDict = {
    "P1": p1,
    "P2": p2,
    ...
    "Pn": pn
}

def myMain(name):
    myDict[name]()

这就是你所需要的全部。


如果name指向一个无效的函数,你可以考虑使用dict.get,并设置一个可调用的默认值——

def myMain(name):
    myDict.get(name, lambda: 'Invalid')()

(这个聪明的技巧是从Martijn Pieters那里学到的)

31

虽然我不太自豪,但:

def myMain(key):
    def ExecP1():
        pass
    def ExecP2():
        pass
    def ExecP3():
        pass
    def ExecPn():
        pass 
    locals()['Exec' + key]()

不过,我建议你把这些放在一个模块或类里,这样真的很糟糕。


如果你愿意为每个函数添加一个装饰器,你可以定义一个装饰器,把每个函数添加到一个字典里:

def myMain(key):
    tasks = {}
    
    def task(task_fn):
        tasks[task_fn.__name__] = task_fn
    
    @task
    def ExecP1():
        print(1)
    @task
    def ExecP2():
        print(2)
    @task
    def ExecP3():
        print(3)
    @task
    def ExecPn():
        print(4)
    
    tasks['Exec' + key]()

另一个选择是把所有函数放在一个类里(或者放在一个不同的模块中),然后使用 getattr

def myMain(key):
    class Tasks:
        def ExecP1():
            print(1)
        def ExecP2():
            print(2)
        def ExecP3():
            print(3)
        def ExecPn():
            print(4)
    
    task = getattr(Tasks, 'Exec' + key)
    task()

撰写回答