通过Python中的数组索引调用函数 [英] Calling functions by array index in Python

查看:164
本文介绍了通过Python中的数组索引调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Python out1,out2,out3等中有一些函数,并希望根据我传入的整数来调用它们。

  def arryofPointersToFns(value):
#call outn其中n =值

有一个简单的方法吗?

解决方案

tl; dr:写一个 n)函数,而不是 out1(),out2(),...,outN(n),不要打扰这个黑客。



我无法想象这个问题在实践中会出现的合理情况。请重新考虑问题的架构;可能会有一个更好的方法来做到这一点(因为将它们存储在列表中意味着除了索引之外的功能没有什么意义;例如,我只能想象如果你正在创建一堆动态生成的thunk,其时间顺序很重要,或类似的东西)。特别是您正在阅读此答案的任何新手用户,请考虑制作更为一般的功能,可以处理所有内容,或将每个功能与更多身份信息相关联,或将其作为课程的一部分等。



说,这是你该怎么做。

  myFuncs = [f0,f1, f2] 
myFuncs [2](...)#calls f2



  myFuncs = {'alice':f1,'bob':f2} 
myFuncs ['alice'](.. 。)

这只是以下两个步骤:

  myFuncs = [f0,f1,f2] 
f = myFuncs [i]
f()

或者如果您没有像上述OP那样的函数myFunc的注册表,则可以使用全局变量(),尽管它是非常黑客的形式并被避免(除非你希望这些功能在你的模块命名空间中可用,在这种情况下可能很好...但是这很可能很少你可能会在子模块中定义这些函数,然后从mysubmodule import * 中的中定义这些函数,反过来又略微皱起来了):

  def fN(n):
return globals()['f'+ str(n)]

def f2():
print(2 was called!)

fN(2)(...)#calls f2
/ pre>




这里有两个其他想法(在答案被接受后添加,前两个评论):



您还可以创建如下的装饰器:

 >>> def makeRegistrar():
... registry = {}
... def registrar(func):
...注册表[func .__ name__] = func
..返回func#通常一个装饰器返回一个包装函数
...#但是这里我们返回func未修改,注册后
... registrar.all =注册表
...返回注册商

,使用如下:

 >>> reg = makeRegistrar()
>>> @reg
... def f1(a):
...返回a + 1
...
>>> @reg
... def f2(a,b):
...返回a + b
...
>>> reg.all
{'f1':<函数f1 at 0x7fc24c381958>,'f2':< function f2 at 0x7fc24c3819e0>}

那么你可以调用reg.all ['f1']。您可以调整 reg 装饰器来跟踪索引,并执行以下操作:

  registry = [] 
index = int(re.regextofindthenumber(func .__ name__))
如果不是index == len(注册表):
raise异常('Expected def f {}但有def f {}')
else:
注册表[index] = func

或者,为避免 globals(),您可以定义一个类:

  class Funcs(object):
def f1():
...
def f2():
...
def num (n):
[代码到这里]

如果你的功能很小,你可以离开 ['f1','f2','f3'] [i]



当然,没有进一步的信息,所有这些建议只是忽略了真正的问题:这种情况永远不会出现,可能是一个严重的架构缺陷的迹象,当你可能希望h ave something(to use your example)like:

 #可能更好的世界
def out(n):
#输出到N,无论什么意思

而不是

 #你现在有
def out1():
#输出到1
def out2():
#output to 2
def outN(n):
#???


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: Write an out(n) function rather than out1(), out2(), ..., outN(n) and don't bother with this hack.

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

or

myFuncs = {'alice':f1, 'bob':f2}
myFuncs['alice'](...)

this is just the following two steps in one step:

myFuncs = [f0,f1,f2]
f = myFuncs[i]
f()

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

and use it like so:

>>> 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>}

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

Alternatively, to avoid globals(), you could define a class:

class Funcs(object):
    def f1():
        ...
    def f2():
        ...
    def num(n):
        [code goes here]

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

rather than

# what you have now
def out1():
    # output to 1
def out2():
    # output to 2
def outN(n):
    # ???

这篇关于通过Python中的数组索引调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆