Вызов функций по индексу массива в Python

У меня есть куча функций в Python out1, out2, out3 и т.д. и хотел бы назвать их на основе целого числа, которое я передаю.

def arryofPointersToFns (value):
     #call outn where n = value

Есть ли простой способ сделать это?

Ответ 1

tl; dr: записать функцию out(n), а не out1(), out2(), ..., outN() и не беспокоиться об этом взломе.

Я не могу представить разумный сценарий, когда этот вопрос возникнет на практике. Пересмотрите архитектуру проблемы; вероятно, будет намного лучший способ сделать это (потому что хранение их в списке означает, что нет ничего значимого в функциях, кроме индекса, например, я могу только представить, что вы захотите сделать это, если бы вы создавали куча динамически генерируемых трюков, где их временный порядок имеет значение или что-то подобное). Особенно начинающие пользователи, которым вы читаете этот ответ, подумайте над тем, чтобы сделать более общую функцию, которая может обрабатывать все, или связывать каждую функцию с некоторой дополнительной идентификационной информацией или придерживаться ее как части класса и т.д.

Итак, вот как вы это сделаете.

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

или

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):
    # ???

Ответ 2

  def array(ar=[]):
     ar = np.array(ar)
     return ar