tl;dr:写一个out(n)
函数而不是out1(), out2(), ..., outN()
不要为这个黑客而烦恼。
我无法想象在实践中会出现这个问题的合理场景。请重新考虑问题的架构;可能有更好的方法来做到这一点(因为将它们存储在列表中意味着除了索引之外这些函数没有任何意义;例如,我只能想象如果您正在创建一堆动态生成的重击,它们的时间顺序很重要,或者类似的东西)。特别是您正在阅读此答案的任何新手用户,请考虑创建一个可以处理所有内容的更通用的函数,或者为每个函数关联一些更多的识别信息,或者将其作为类的一部分等等。
也就是说,这就是你要做的事。
myFuncs = [f0,f1,f2]
myFuncs[2](...) #calls f2
or
myFuncs = {'alice':f1, 'bob':f2}
myFuncs['alice'](...) #calls f1
这只是以下两个步骤的一步:
myFuncs = [f0,f1,f2]
f = myFuncs[i]
f(...) #calls fi
或者,如果您没有像上面所说的那样的函数“myFunc”的注册表,您可以使用 globals(),尽管它是一种极其黑客的形式并且应该避免(除非您希望这些函数在您的模块命名空间中可用) ,在这种情况下也许没问题......但这种情况可能很少发生,您可能宁愿在子模块中定义这些函数from mysubmodule import *
他们,这反过来又有点令人皱眉):
def fN(n):
return globals()['f'+str(n)]
def f2():
print("2 was called!")
fN(2)(...) #calls f2
这里还有另外两个想法(在接受答案和前两条评论后添加):
您还可以创建一个像这样的装饰器:
>>> 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
装饰器来跟踪索引并执行以下操作:
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()
,你可以定义一个类:
class Funcs(object):
def f1():
...
def f2():
...
def num(n):
[code goes here]
如果你的函数数量很少,你可以逃脱['f1','f2','f3'][i]
.
当然,如果没有进一步的信息,所有这些建议都只是忽略了真正的问题:这种情况永远不应该出现,并且可能是严重架构缺陷的迹象,当您可能宁愿拥有类似的东西(使用您的示例)时:
# 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):
# ???