如何使用 c api 在 python 中实现 Closure?
How to implement Closure in python using c api?
我正在尝试使用 python c api:
实现类似这样的功能
def get_add(x):
def add(y):
return x + y
return add
add5 = get_add(5)
add10 = get_add(10)
add5(12) # 17
add10(12) # 22
模块使用示例:
from mymodule import get_add
add5 = get_add(5)
add10 = get_add(10)
add5(12) # 17
add10(12) # 22
其中 mymodule
是用 c.
写的
我从未真正见过 PyFunction_SetClosure
使用过,但我希望用它来修改现有的 Python 函数对象以更改闭包变量。它可能不适合实现从头开始生成带有闭包的新函数,因为这不会根据 PyFunctionObject
实现(因为它们专门用于处理 Python 字节码等)。
您正在寻找的是具有 __call__
属性的自定义 C API Python 类型。该类型的构造函数设置闭包,调用属性实现您的函数 add
.
我将勾勒出基本方案,但没有兴趣生成完整的工作示例。
首先定义将成为您的 C API 对象的结构:
typedef struct {
PyObject_HEAD
int a; // I'm assuming you only want to add ints
} Adder;
接下来定义一个 __init__
函数来生成该结构(这也可以是 __new__
函数,但我们现在不要太担心......)
static int
Adder_init(Adder *self, PyObject *args, PyObject *kwds) {
// parse args and kwds to get the argument "a"
// ...
self->a = a;
return 0; // success!
};
接下来定义 __call__
函数来添加
static PyObject*
Adder_call(Adder *self, PyObject *args, PyObject *kwds) {
// parse args and kwds to get the argument "b"
// ...
int result = self->a + b;
return PyLong_FromLong(result);
};
完成这两个函数后,您需要定义类型对象。同样,这只是在下面勾勒出来:
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
// other fields as needed
.tp_init = Adder_init,
.tp_call = Added_call,
};
最终将此类型作为 get_add
公开给 Python,并且您的行为完全符合您的要求。
我正在尝试使用 python c api:
实现类似这样的功能def get_add(x):
def add(y):
return x + y
return add
add5 = get_add(5)
add10 = get_add(10)
add5(12) # 17
add10(12) # 22
模块使用示例:
from mymodule import get_add
add5 = get_add(5)
add10 = get_add(10)
add5(12) # 17
add10(12) # 22
其中 mymodule
是用 c.
我从未真正见过 PyFunction_SetClosure
使用过,但我希望用它来修改现有的 Python 函数对象以更改闭包变量。它可能不适合实现从头开始生成带有闭包的新函数,因为这不会根据 PyFunctionObject
实现(因为它们专门用于处理 Python 字节码等)。
您正在寻找的是具有 __call__
属性的自定义 C API Python 类型。该类型的构造函数设置闭包,调用属性实现您的函数 add
.
我将勾勒出基本方案,但没有兴趣生成完整的工作示例。
首先定义将成为您的 C API 对象的结构:
typedef struct {
PyObject_HEAD
int a; // I'm assuming you only want to add ints
} Adder;
接下来定义一个 __init__
函数来生成该结构(这也可以是 __new__
函数,但我们现在不要太担心......)
static int
Adder_init(Adder *self, PyObject *args, PyObject *kwds) {
// parse args and kwds to get the argument "a"
// ...
self->a = a;
return 0; // success!
};
接下来定义 __call__
函数来添加
static PyObject*
Adder_call(Adder *self, PyObject *args, PyObject *kwds) {
// parse args and kwds to get the argument "b"
// ...
int result = self->a + b;
return PyLong_FromLong(result);
};
完成这两个函数后,您需要定义类型对象。同样,这只是在下面勾勒出来:
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
// other fields as needed
.tp_init = Adder_init,
.tp_call = Added_call,
};
最终将此类型作为 get_add
公开给 Python,并且您的行为完全符合您的要求。