【问题标题】:How to implement Closure in python using c api? [closed]如何使用c api在python中实现闭包? [关闭]
【发布时间】:2021-10-31 22:49:35
【问题描述】:

我正在尝试使用 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 中。

【问题讨论】:

  • 请告诉我们您想要的结果是什么,您提供的代码 sn-ps 或问题的当前结果是什么。逐步引导我们完成您的代码所做的工作,直到我们解决您的具体问题/问题。这样,您还可以将问题的标题编辑为更具体且可直接回答的问题。在发布您的问题之前,您可以使用this checklist 作为您的指南。

标签: python c closures python-c-api


【解决方案1】:

我实际上从未见过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,你就有了一些行为与你想要的完全一样的东西。

【讨论】:

    猜你喜欢
    • 2017-06-13
    • 2016-04-04
    • 1970-01-01
    • 2021-10-15
    • 2019-04-26
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多