Python中通过数组索引调用函数
问题描述
我在 Python out1、out2、out3 等中有一堆函数,我想根据我传入的整数调用它们.
I have a bunch of functions in Python out1, out2, out3 etc. and would like to call them based on an integer I pass in.
def arryofPointersToFns (value):
#call outn where n = value
有没有简单的方法可以做到这一点?
Is there an easy way to do this?
解决方案
tl;dr: 写一个 out(n)
函数而不是 out1(), out2(), ..., outN()
并且不要打扰这个黑客.
tl;dr: Write an out(n)
function rather than out1(), out2(), ..., outN()
and don't bother with this hack.
我无法想象在实践中会出现这个问题的合理场景.请重新考虑问题的架构;可能有更好的方法来做到这一点(因为将它们存储在列表中意味着除了索引之外的函数没有任何意义;例如,我只能想象如果你正在创建你想要这样做一堆动态生成的 thunk,它们的时间顺序很重要,或者类似的东西).尤其是您正在阅读此答案的任何新手用户,请考虑制作一个可以处理所有内容的更通用的函数,或者为每个函数关联更多的识别信息,或者将其作为类的一部分等等.
I cannot imagine a reasonable scenario where this question would come up in practice. Please reconsider the architecture of the problem; there is likely to be a much better way to do this (because storing them in a list implies there is nothing meaningful about the functions except the index; for example, I can only imagine that you'd want to do this if you were creating a bunch of dynamically-generated thunks where their temporal ordering matters, or something similar). Especially any novice users you are reading this answer, consider making a more general function that can handle everything, or associating to each function some more identifying information, or sticking it as part of a class, etc.
也就是说,这就是你的做法.
That said, this is how you'd do it.
myFuncs = [f0,f1,f2]
myFuncs[2](...) #calls f2
或
myFuncs = {'alice':f1, 'bob':f2}
myFuncs['alice'](...) #calls f1
这只是以下两步合二为一:
this is just the following two steps in one step:
myFuncs = [f0,f1,f2]
f = myFuncs[i]
f(...) #calls fi
或者,如果您没有像上面所说的 OP 那样的函数 'myFunc' 的注册表,您可以使用 globals(),尽管它是一种非常骇人听闻的形式并且应该避免(除非您希望这些函数在你的模块命名空间,在这种情况下可能没问题......但这可能很少见,你可能宁愿在子模块中定义这些函数,然后 from mysubmodule import *
它们,它在微微皱眉):
or if you don't have a registry of functions 'myFunc' like the OP said above, you can use globals(), though it is extremely hackish form and to be avoided (unless you want those functions to be available in your module namespace, in which case maybe it's fine... but this is probably rarely the case, and you'd probably rather define those functions in a submodule then from mysubmodule import *
them, which is in turn slightly frowned upon):
def fN(n):
return globals()['f'+str(n)]
def f2():
print("2 was called!")
fN(2)(...) #calls f2
<小时>
这里有两个其他想法(在接受答案和前两条评论后添加):
here are two other ideas (added after answer was accepted and first two comments):
你也可以像这样创建一个装饰器:
You can also create a decorator like this:
>>> def makeRegistrar():
... registry = {}
... def registrar(func):
... registry[func.__name__] = func
... return func # normally a decorator returns a wrapped function,
... # but here we return func unmodified, after registering it
... registrar.all = registry
... return registrar
并像这样使用它:
>>> reg = makeRegistrar()
>>> @reg
... def f1(a):
... return a+1
...
>>> @reg
... def f2(a,b):
... return a+b
...
>>> reg.all
{'f1': <function f1 at 0x7fc24c381958>, 'f2': <function f2 at 0x7fc24c3819e0>}
然后你可以调用 reg.all['f1'].您可以调整 reg
装饰器以跟踪索引并执行以下操作:
then you can call reg.all['f1']. You could adapt the reg
decorator to keep track of the indexing and do something like:
registry = []
index = int(re.regextofindthenumber(func.__name__))
if not index==len(registry):
raise Exception('Expected def f{} but got def f{}')
else:
registry[index] = func
或者,为了避免 globals()
,您可以定义一个类:
Alternatively, to avoid globals()
, you could define a class:
class Funcs(object):
def f1():
...
def f2():
...
def num(n):
[code goes here]
如果您的函数数量很少,您可以使用 ['f1','f2','f3'][i]
.
If your number of functions is small, you could get away with ['f1','f2','f3'][i]
.
当然,没有更多信息,所有这些建议都只是忽略了真正的问题:这种情况永远不应该出现,并且可能是严重架构缺陷的迹象,而您可能更愿意拥有一些东西(使用您的示例)喜欢:
Of course without further information, all these suggestions are just ignoring the real problem: this situation should never come up, and is a possibly a sign of a serious architecture flaw, when you'd probably rather have something (to use your example) like:
# a possibly-better world
def out(n):
# output to N, whatever that means
而不是
# what you have now
def out1():
# output to 1
def out2():
# output to 2
def outN(n):
# ???
相关文章