【问题标题】:Iterate over a list to create functions遍历列表以创建函数
【发布时间】:2020-07-18 23:27:09
【问题描述】:

我正在尝试使用 solve_ivp 求解大型微分方程组。

from scipy import integrate
sol = integrate.solve_ivp(func_system, (0,100), initial_value_array, t_eval)

func_system 是一个微分方程组,取决于X 列表的长度:

X = ['a','b','c','d',...]

K1, K2, K3, K4 = [1, 2, 2, 1]

def dadt(X,t):
    return -K1*X[0]+K2*X[1]
def dbdt(X,t):
    return K2*X[0]-(K2+K3+K4)*X[1]
def dcdt (X,t):
    return ....
def dddt (X,t):
    return ....

等等。

def func_system(X,t):
    return np.array([dadt(X,t), dbdt(X,t), dcdt(X,t), dddt(X,t)])

因为 X 可能很长,所以我想遍历列表以创建函数名称。例如,

dxdt = ['d'+a+'dt' for a in X]

for i in range(len(dxdt)):
    def dxdt[i]:
        return something

,我会从数据框中得到“一些东西”。我的问题是是否可以遍历列表来创建函数名称?

【问题讨论】:

    标签: python list function loops


    【解决方案1】:

    为什么不使用dict?键是名称和值函数。

    【讨论】:

    • 哦,来吧!我现在尝试 10 分钟来更改函数对象的 name 属性。我是如此接近!但是是的......你可能是对的:(
    • 我认为您的意思是“价值函数”,我的回答可能就是您的建议
    【解决方案2】:

    如前所述,您可以简单地使用例如。 dict 来完成这个。不是最优雅的解决方案,但绝对可行,即使所有函数共享相同的签名,也不会那么难看:

    dispatch = {
      'dadt': lambda X, t: -K1*X[0]+K2*X[1],
      'dbdt': lambda X, t: K2*X[0]-(K2+K3+K4)*X[1],
      # you get the idea
    }
    
    # later, eg. to call dadt(my_vector, t):
    rval = dispatch["dadt"](my_vector, t)
    
    # or, if you want to have pretty functions eg. that you call often, functions
    # are just values too:
    
    dadt = dispatch["dadt"]
    dadt(my_vector, t)
    

    【讨论】:

    • 我个人会使用 lambdas,但我认为 exec 表明可以在代码中动态创建真正的函数。
    • 这通常是个很糟糕的主意,试图解释为什么:)
    【解决方案3】:

    这是你想要完成的吗?

    Python 3.6.9 (default, Oct 17 2019, 06:42:36) 
    Type 'copyright', 'credits' or 'license' for more information
    IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.
    
    In [1]: X = ['a','b','c','d']                                                                                                                                                                                                              
    
    In [2]: K1, K2, K3, K4 = [1, 2, 2, 1]                                                                                                                                                                                                      
    
    In [3]: code = ['def d{symbol}dt(X, t): return "something"'.format(symbol=symbol) for symbol in X]                                                                                                                                         
    
    In [4]: functions = {}                                                                                                                                                                                                                     
    
    In [5]: for func in code: 
       ...:     exec(func, {}, functions) 
       ...:                                                                                                                                                                                                                                    
    
    In [6]: functions                                                                                                                                                                                                                          
    Out[6]: 
    {'dadt': <function dadt(X, t)>,
     'dbdt': <function dbdt(X, t)>,
     'dcdt': <function dcdt(X, t)>,
     'dddt': <function dddt(X, t)>}
    
    In [7]: functions['dadt'](1, 0)                                                                                                                                                                                                            
    Out[7]: 'something'
    

    【讨论】:

    • 将代码写成字符串是非常糟糕的,因为很难检测到其中的任何错误,因为语法分析会绕过此类字符串。它与使用 eval 基本相同,有很多好帖子为什么你不应该使用它。但是,由于函数名可以用作 var,因此很容易定义这些函数,然后使用类似的循环在链中调用它们。
    猜你喜欢
    • 2017-05-07
    • 2018-04-12
    • 1970-01-01
    • 2021-03-06
    • 2021-03-24
    • 2019-04-27
    • 2013-08-11
    • 2013-07-01
    • 2021-03-31
    相关资源
    最近更新 更多