调用与升压蟒蛇的输入参数变量数量Python函数

问题描述:

是否有可能调用具有从内部的boost :: python的可变数量的输入参数一个Python函数:调用与升压蟒蛇的输入参数变量数量Python函数

在Python中,我定义一个函数

def py_fn1(a): 
    return 2 * a 

def py_fn2(a, b): 
    return a+b 

def call_fn_py(fn, *args): 
    return fn(*args) 

a = call_fn_py(py_fn1, 15) # returns 30 
b = call_fn_py(py_fn2, 10, 11) # returns 21 

根据评论给出结果。我想用boost python在C++中实现call_fn(fn,* args)。到目前为止,我有:

using namespace boost::python; 
object call_fn(object fn, tuple arg_in) 
{ 
return fn(arg_in); 
} 


BOOST_PYTHON_MODULE(python_addins) 
{ 
    using namespace boost::python; 
def("call_fn", &call_fn); 
} 

但随后做这样的事情:

import python_addins 

d = python_addins.call_fn(py_fn1, (5,)) # returns (5,5) 

这是不是一上午后。我如何编写call_fn来表现得像call_fn_py?

谢谢,马克

它可以调用一个python函数的参数个数可变。有两种方法:

  • 通过创建一组call_fn函数模仿可变数量的自变量。
  • 利用python将多个对象打包并解包为元组的能力。

第一种方法是为通用的C++编程相当普遍。它需要创建一组根据参数数量而变化的重载函数:call_fn(fn),call_fn(fn, A1),call_fn(fn, A1, ...An)。使用C++ 11可变参数模板函数可以减少样板代码的数量。但是,在定义包装时,必须指定模板函数的精确类型。因此,这种方法将基于包含什么样的模板实例来限制参数的数量。

#include <boost/python.hpp> 

using boost::python; 
object call_fn1(object fn, object a1) 
{ 
    return fn(a1); 
} 
object call_fn2(object fn, object a1, object a2) 
{ 
    return fn(a1, a2); 
} 
object call_fn3(object fn, object a1, object a2, object a3) 
{ 
    return fn(a1, a2, a3); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    def("call_fn", &call_fn1); 
    def("call_fn", &call_fn2); 
    def("call_fn", &call_fn3); 
} 

这里是一个演示:

>>> def py_fn1(a): return 2 * a 
... 
>>> def py_fn2(a, b): return a + b 
... 
>>> def call_fn_py(fn, *args): 
...  from example import call_fn 
...  return call_fn(fn, *args) 
... 
>>> call_fn_py(py_fn1, 15) 
30 
>>> call_fn_py(py_fn2, 10, 11) 
21 

第二种方法利用元组。它需要调用者将参数打包到一个元组中,并调用函数来解压参数。但是,由于在python中执行元组打包和解压缩更容易,因此example.call_fn可以用python打补丁,以便函数参数用辅助函数进行装饰,该辅助函数可以在委派前解开参数。

在C++中,创建一个call_fn函数,该函数接受单个boost::python::tuple参数。现在

#include <boost/python.hpp> 

using namespace boost::python; 
object call_fn(object fn, tuple args) 
{ 
    return fn(args); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    def("call_fn", &call_fn); 
} 

,创建example_ext.py将修补example.call_fn

import example 

def patch_call_fn(): 
    # Store handle to unpatched call_fn. 
    original = example.call_fn 

    # Helper function to create a closure that unpacks arguments 
    # before delegating to the user function. 
    def unpack_args(fn): 
     def wrapper(args): 
      return fn(*args) 
     return wrapper 

    # The patched function that will wrap the user function. 
    def call_fn(fn, *args): 
     return original(unpack_args(fn), args) 

    return call_fn 

# Patch example. 
example.call_fn = call_fn = patch_call_fn() 

同样的演示可以使用,唯一需要改变的是example_ext需要进口,而不是example

>>> def py_fn1(a): return 2 * a 
... 
>>> def py_fn2(a, b): return a + b 
... 
>>> def call_fn_py(fn, *args): 
...  from example_ext import call_fn 
...  return call_fn(fn, *args) 
... 
>>> call_fn_py(py_fn1, 15) 
30 
>>> call_fn_py(py_fn2, 10, 11) 
21