具有子函数及其参数作为参数的函数

我想建立一个熊猫随机数据框。为了实现这个目的,我需要一个 Python 函数作为参数:

  • numpy 分布

  • 他们的论点

例如 :

分布1:正常| 参数:手段 = 0 ,标准开发 = 1 ,大小 = 100

分布2:均匀| 参数:低 = 0,高 = 1,大小 = 100

等等...

我事先不知道不同的分布及其论点会是什么。

然后,主函数将使用每个相应的参数生成分布的随机样本。

我尝试过类似的东西:


import numpy as np


def myfun( **kwargs ) :

    for k , v in kwargs.items() :

        print( k )

        print( v )

当我使用这些参数调用该函数时:


myfun( fun_1 = 'np.random.normal' , arg_1 = { 'loc' : 0 , 'scale' : 1 , 'size' : 7 } ,

       fun_2 = 'np.random.uniform' , arg_2 = { 'low' : 0 , 'high' : 1 , 'size' : 7 } )

输出是:


fun_1

np.random.normal

arg_1

{'loc': 0, 'scale': 1, 'size': 7}

fun_2

np.random.uniform

arg_2

{'low': 0, 'high': 1, 'size': 7}

但我的目的不是打印所需的分布及其相关参数,而是为每个分布生成一个样本。


慕后森
浏览 120回答 2
2回答

慕侠2389804

注意,函数应该是函数,而不是字符串,这样实现才能工作如果您想返回使用一组 调用的函数kwargs,那么您已经非常接近了。我会使用位置参数 for func,然后你可以传入kwargs,func这更明确一点:def myfunc(func, **kwargs):&nbsp; &nbsp; return func(**kwargs)然后,您可以将每对包装func, **kwargs为元组,并执行一个 for 循环:# This would be called likesomelist = [(np.random.normal, { 'loc' : 0 , 'scale' : 1 , 'size' : 7 }),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (np.random.uniform , { 'low' : 0 , 'high' : 1 , 'size' : 7 })]results = []# append results to a listfor func, kwargs in somelist:&nbsp; &nbsp; results.append(myfunc(func, **kwargs))通过这种方式,您不必担心如何命名任何变量,并且更具可读性。您知道循环将处理成对的项目,在这种情况下是func, kwarg成对的,您的函数可以显式处理这些处理字符串调用所以有一些方法可以完成这个任务,它们有点棘手,但总体上不应该是可怕的。您需要修改myfunc以处理函数名称:# func is now a string, unlike abovedef myfunc(func, **kwargs):&nbsp; &nbsp; # function will look like module.class.function&nbsp; &nbsp; # so split on '.' to get each component. The first will&nbsp;&nbsp; &nbsp; # be the parent module in global scope, and everything else&nbsp; &nbsp; # is collected into a list&nbsp; &nbsp; mod, *f = func.split('.') # f is a list of sub-modules like ['random', 'uniform']&nbsp; &nbsp; # func for now will just be the module np&nbsp; &nbsp; func = globals().get(mod)&nbsp; &nbsp; for cls in f:&nbsp; &nbsp; &nbsp; &nbsp; # get each subsequent level down, which will overwrite func to&nbsp; &nbsp; &nbsp; &nbsp; # first be np.random, then np.random.uniform&nbsp; &nbsp; &nbsp; &nbsp; func = getattr(func, cls)&nbsp; &nbsp; return func(**kwargs)我使用的原因globals().get(mod)是 a) 我假设您可能并不总是使用相同的模块,并且 b) 调用重命名的 import fromsys.modules将产生 a KeyError,这不是您想要的:import sysimport numpy as npsys.modules['np'] # KeyErrorsys.modules['numpy']# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'># globals avoids the naming conflictglobals()['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 npgetattr(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 directlygetattr(np, 'random.uniform')# AttributeError所以,总共:import numpy as npfunc, kwargs = ('np.random.normal', { 'loc' : 0 , 'scale' : 1 , 'size' : 7 })myfunc(func, **kwargs)array([ 0.83276777,&nbsp; 2.4836389 , -1.07492873, -1.20056678, -0.36409906,&nbsp; &nbsp; &nbsp; &nbsp;-0.76543554,&nbsp; 0.90191746])您可以将其扩展到第一部分中的代码

绝地无双

您可以设计一个将其他函数作为输入并执行它们的函数。这就是**运营商所做的:def myfun(**kwargs):&nbsp; &nbsp; kwargs['fun_1'](**kwargs['arg_1'])&nbsp; # calls the function kwargs[fun_1] with the keyword args given in kwargs[arg_1]&nbsp; &nbsp; kwargs['fun_2'](**kwargs['arg_2'])然后,您将像这样指定您的 kwargs:myfun(fun_1=np.random.normal,&nbsp;&nbsp; &nbsp; &nbsp; arg_1={'loc': 0, 'scale': 1, 'size': 7},&nbsp; &nbsp; &nbsp; fun_2=np.random.uniform,&nbsp; &nbsp; &nbsp; arg_2={'low': 0, 'high': 1, 'size': 7},&nbsp; &nbsp; &nbsp;)请注意如何np.random.normal不在引号中 - 我们通过引用引用实际函数,但尚未调用它(因为我们想在 中执行此操作myfun(),而不是现在)。我认为这个操作符(*列表和**字典)没有正式名称,但我称它为解包操作符,因为它将数据结构解包到函数参数中。在这种情况下,声明显式命名参数通常更安全- 您需要提出一种模式,以便使用您的函数的人知道他们应该如何命名他们的关键字。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python