微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在python函数中添加数学函数作为参数

如何解决如何在python函数中添加数学函数作为参数

我知道有关于将函数传递给函数的类似问题,但我不清楚针对我的特定问题的有效解决方案。

以下函数有效,但公式是静态的。它仅适用于固定函数,即(在数学伪代码中)f(a) = 3^a mod 17 = b where f(11) = 7

def get_a(b):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    a = 1
    while(1):
            x = pow(3,a) % 17
            if x == b:
                return a
            if a > 10000:
                return -1
            a += 1


def main():
    b = 7
    a = get_a(7)
    print(F'The preimage a of b={b} is: {a}')


if __name__ == '__main__':
    main()

我想让用户传入任何给定的函数。首先,我实现了一些稍微复杂但仍然非常简单的东西。

def get_a_variable(b,base,mod):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    a = 1
    while(1):
        # print(F'a:{a},b{b}')
        x = pow(base,a) % mod
        # print(F'x:{x}')
        if x == b:
            return a
        if a > 10000:
            return -1
        a += 1

def main():
    b = 7
    a = get_a(7)
    print(F'The preimage a of b={b} is: {a}')
    a = get_a_variable(7,3,17)
    print(F'Again,the preimage a of b={b} is: {a}')

这行得通,但我想让它更有活力。

为了尝试实现这一点,我创建了一个可以作为参数传递的新函数

def power_mod_function(base,x,mod):
  return power(base,x) % mod

我不确定应该如何处理试验值 arg x 或者它是否应该在这函数中。

然后我“分叉”了接受回调的“get_a(b)”函数,我相信

def get_a_dynamic(b,crypt_func):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    a = 1
    while(1):
            x = crypt_func() # Not sure how to manage the arg passing here
            if x == b:
                return a
            if a > 10000:
                return -1
            a += 1

然后我更新了 main():

def main():
    b = 7
    a = get_a(7)
    print(F'The preimage a of b={b} is: {a}')
    a = get_a_dynamic(b,power_mod_function(3,17)) # Not sure how to pass my middle arg!! 
    print(F'Again the preimage a of b={b} is: {a}')

我收到以下错误消息:

 python pre_img_finder.py
The preimage a of b=7 is: 11
Traceback (most recent call last):
  File "pre_img_finder.py",line 45,in <module>
    main()
  File "pre_img_finder.py",line 41,in main
    a = get_a_dynamic(b,17))
NameError: name 'x' is not defined

我不知道如何正确设置并进行变量传递,以便我可以在 main 中传递一次静态变量,而中间的测试变量 x 将始终递增并最终找到我想要的结果。

也许我只需要接收一个以“类型”参数开头的函数,该参数充当一种开关,然后根据类型采用可变数量的参数。例如,我们可以将上面的函数称为 base-power-mod 函数或 (bpm),其中“power”是我们正在寻找的答案,即 a 是技术术语中 b 的原像。然后调用

main():
    a = get_a_dynamic(7,("bpm",17))

然后以这种方式实施? 感谢您的帮助!

解决方法

使用 :help submatch() 向函数传递额外的任意数量的参数。

*args

然后像这样在你的主程序中调用它

def get_a_dynamic(b,crypt_func,*args):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    a = 1
    while(1):
            x = crypt_func(*args) 
            if x == b:
                return a
            if a > 10000:
                return -1
            a += 1
,

生成带有部分定义参数的动态函数的方法是... functools.partial


from functools import partial

def get_a_variable_with_func(b,func):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    a = 1
    while(1):
        x = func(a)
        if x == b:
            return a
        if a > 10000:
            return -1
        a += 1

b = 7

def power_mod_function(base,mod,x):
    return (base ** x) % mod

partial_func = partial(power_mod_function,3,17)

a = get_a_variable_with_func(7,partial_func)
print(a)
>>>
11

顺便说一句,这更像pythonic:

from functools import partial

def get_a_variable_with_func(b,func):
    '''
    Get preimage a from A for f(a) = b where b in B
    '''
    for a in range(10001):
        if func(a) == b:
            return a
    return -1

def power_mod_function(base,x):
    return (base ** x) % mod

a = get_a_variable_with_func(7,partial(power_mod_function,17))
print(a)

,

当你这样做时:

a = get_a_dynamic(b,power_mod_function(3,x,17))

您没有将 power_mod_function 传递给 get_a_dynamic,而是传递了它的结果 反而。要传递函数,您只需传递函数名称。

因此,因为该函数需要一个 get_a_dynamic 内部值(x arg)以及两个外部参数(3 和 17),您必须将这两个参数分别传递给 get_a_dynamic 以便它能够调用带有三个所需参数的传递函数。

为此,可以使用 AnkurSaxena 的建议,特别是如果 args 的数量可以变化。但是你也可以这样声明:

def get_a_dynamic(b,pow,mod):

然后像这样使用它:

a = get_a_dynamic(b,power_mod_function,17))
,

你会做这样的事情:

def get_a_dynamic(b,function,argtuple):
    # …
    x = function(*argtuple) # star-operator unpacks a sequence
    # … et cetera

...本质上。然后,您可以在传递它时始终检查 argtuple 的范围,或者对您的调用约定一丝不苟——但我认为,星号运算符解包位是您正在寻找的关键。

如果您想将函数的名称作为字符串传递(根据您的示例),您可以执行以下操作:

function = globals()["bpm"] # insert your passed string argument therein

...但这有点粗略,我不推荐它 - 在这种情况下,最好预先填充一个将函数字符串名称映射到函数本身的字典。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。