Обратите внимание, что для работы этой реализации функции должны быть функциями, а не строками
Если вы хотите вернуть функцию, вызванную с набором kwargs
, вы довольно близки. Я бы использовал позиционный аргумент для func
, тогда вы можете передать kwargs
в func
, что немного более явно:
def myfunc(func, **kwargs):
return func(**kwargs)
Затем вы можете обернуть каждую пару func, **kwargs
в кортежи и выполнить цикл for:
# This would be called like
somelist = [(np.random.normal, { 'loc' : 0 , 'scale' : 1 , 'size' : 7 }),
(np.random.uniform , { 'low' : 0 , 'high' : 1 , 'size' : 7 })]
results = []
# append results to a list
for func, kwargs in somelist:
results.append(myfunc(func, **kwargs))
Делая это таким образом, вам не нужно беспокоиться о том, что вы назовете вашей переменной, и это немного более читабельно. Вы знаете, что цикл будет работать с парами элементов, в данном случае с func, kwarg
парами, и ваша функция может обрабатывать их явно
Обработка строковых вызовов
Так что есть несколько способов выполнить эту задачу, которые немного сложнее, но в целом не должны быть ужасными. Вам нужно изменить myfunc
для обработки имени функции:
# func is now a string, unlike above
def myfunc(func, **kwargs):
# function will look like module.class.function
# so split on '.' to get each component. The first will
# be the parent module in global scope, and everything else
# is collected into a list
mod, *f = func.split('.') # f is a list of sub-modules like ['random', 'uniform']
# func for now will just be the module np
func = globals().get(mod)
for cls in f:
# get each subsequent level down, which will overwrite func to
# first be np.random, then np.random.uniform
func = getattr(func, cls)
return func(**kwargs)
Причина, по которой я использую globals().get(mod)
, заключается в том, что а) я предполагаю, что вы не всегда используете один и тот же модуль, и б) вызов переименованного импорта из sys.modules
даст KeyError
, что не ' т, что вы хотите:
import sys
import numpy as np
sys.modules['np'] # KeyError
sys.modules['numpy']
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
# globals avoids the naming conflict
globals()['np']
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
Затем getattr(obj, attr)
возвратит каждый последующий модуль:
import numpy as np
getattr(np, 'random')
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
# the dotted access won't work directly
getattr(np, 'random.uniform')
# AttributeError
Итак, всего:
import numpy as np
func, kwargs = ('np.random.normal', { 'loc' : 0 , 'scale' : 1 , 'size' : 7 })
myfunc(func, **kwargs)
array([ 0.83276777, 2.4836389 , -1.07492873, -1.20056678, -0.36409906,
-0.76543554, 0.90191746])
И вы можете просто расширить это до кода в первом разделе