使用字典选择要执行的函数
我想用函数式编程来创建一个字典,这个字典里包含一个键和一个要执行的函数:
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()