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

我正在尝试使用函数式编程来创建一个字典,其中包含一个键和一个要执行的函数:

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"]() #this will call ExecP1()

我真正的问题是,我有大量的这些项目,我做了一个库,将处理他们,所以最终用户只需要调用 myMain("P1")

我认为使用检查模块,但我不太确定如何做到这一点。

我避免的理由:

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

我必须保护代码,因为我正在使用它来在我的应用程序中提供一个脚本特性。

166315 次浏览

Simplify, simplify, simplify:

def p1(args):
whatever


def p2(more args):
whatever


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


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

That's all you need.


You might consider the use of dict.get with a callable default if name refers to an invalid function—

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

(Picked this neat trick up from Martijn Pieters)

#!/usr/bin/python


def thing_a(arg=None):
print 'thing_a', arg


def thing_b(arg=None):
print 'thing_b', arg


ghetto_switch_statement = {
'do_thing_a': thing_a,
'do_thing_b': thing_b
}


ghetto_switch_statement['do_thing_a']("It's lovely being an A")
ghetto_switch_statement['do_thing_b']("Being a B isn't too shabby either")


print "Available methods are: ", ghetto_switch_statement.keys()

Not proud of it, but:

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

I do however recommend that you put those in a module/class whatever, this is truly horrible.


If you are willing to add a decorator for each function, you can define a decorator which adds each function to a dictionary:

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]()

Another option is to place all the functions under a class (or in a different module) and use 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()

You are wasting your time:

  1. You are about to write a lot of useless code and introduce new bugs.
  2. To execute the function, your user will need to know the P1 name anyway.
  3. Etc., etc., etc.

Just put all your functions in the .py file:

# my_module.py


def f1():
pass


def f2():
pass


def f3():
pass

And use them like this:

import my_module


my_module.f1()
my_module.f2()
my_module.f3()

or:

from my_module import f1
from my_module import f2
from my_module import f3


f1()
f2()
f3()

This should be enough for starters.

Simplify, simplify, simplify + DRY:

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


@task
def p1():
whatever


@task
def p2():
whatever


def my_main(key):
tasks[key]()
def p1( ):
print("in p1")


def p2():
print("in p2")


myDict={
"P1": p1,
"P2": p2


}


name=input("enter P1 or P2")

myDictname

# index dictionary by list of key names


def fn1():
print "One"


def fn2():
print "Two"


def fn3():
print "Three"


fndict = {"A": fn1, "B": fn2, "C": fn3}


keynames = ["A", "B", "C"]


fndict[keynames[1]]()


# keynames[1] = "B", so output of this code is


# Two

You can just use

myDict = {
"P1": (lambda x: function1()),
"P2": (lambda x: function2()),
...,
"Pn": (lambda x: functionn())}
myItems = ["P1", "P2", ..., "Pn"]


for item in myItems:
myDict[item]()

This will call methods from dictionary

This is python switch statement with function calling

Create few modules as per the your requirement. If want to pass arguments then pass.

Create a dictionary, which will call these modules as per requirement.

    def function_1(arg):
print("In function_1")


def function_2(arg):
print("In function_2")


def function_3(fileName):
print("In function_3")
f_title,f_course1,f_course2 = fileName.split('_')
return(f_title,f_course1,f_course2)




def createDictionary():


dict = {


1 : function_1,
2 : function_2,
3 : function_3,


}
return dict


dictionary = createDictionary()
dictionary[3](Argument)#pass any key value to call the method

Often classes are used to enclose methods and following is the extension for answers above with default method in case the method is not found.

class P:


def p1(self):
print('Start')


def p2(self):
print('Help')


def ps(self):
print('Settings')


def d(self):
print('Default function')


myDict = {
"start": p1,
"help": p2,
"settings": ps
}


def call_it(self):
name = 'start'
f = lambda self, x : self.myDict.get(x, lambda x : self.d())(self)
f(self, name)




p = P()
p.call_it()
class CallByName():
    

def method1(self):
pass


def method2(self):
pass


def method3(self):
pass


def get_method(self, method_name):
method = getattr(self, method_name)
return method()




callbyname = CallByName()
method1 = callbyname.get_method(method_name)


```