【问题标题】:Cython and constructors of classesCython 和类的构造函数
【发布时间】:2012-10-23 12:07:06
【问题描述】:

我对 Cython 使用默认构造函数有疑问。

我的C++类Node如下

Node.h

class Node
{
public:
    Node()
    { 
        std::cerr << "calling no arg constructor" << std::endl;
            w=0.0;
        d=0.0;
    }
    Node(double val, double val2);
    {
            std::cerr << "calling 2 args constructor" << std::endl;
        this->w=val;
        this->d=val2;
    }
private:
    double d,w;
}

如下包裹在 Cython 中

cdef extern from "Node.h":
    cdef cppclass Node:
        Node() except +
        Node(double val1, double val2) except +
        double d
        double w

cdef class pyNode:
    cdef Node *thisptr      # hold a C++ instance which we're wrapping

    def __cinit__(self):
        self.thisptr = new Node()

    def __cinit__(self, double val1, double val2):
        self.thisptr = new Node(val1,val2)

    def __dealloc__(self):
        del self.thisptr

    def __repr__(self):
        return "d=%s w=%s" % (self.thisptr.w, self.thisptr.w )

Cython 代码编译良好,尤其是从 Python 调用时

from pyNode import pyNode as Node
n=Node(1.0,2.0)

我得到了预期的calling 2 args constructor 字符串,但是如果我尝试使用“无参数”构造函数从 python 声明一个 Node 对象(应该正确声明为__cinit__(self),我没有得到任何输出,这意味着没有调用无参数构造函数!

如何从包装类的 cinit 方法中显式调用它?

【问题讨论】:

    标签: c++ python constructor cython default-constructor


    【解决方案1】:

    这里的问题是你不能像 __cinit__() 那样重载(如 only cdef functions can be overloaded) - 相反,让它采用默认值,然后根据需要调用正确的东西。

    编辑:本质上,您需要以更接近普通 Python 代码的方式实现该函数,而不是使用重载:

    def __cinit__(self, double val1=-1, double val2=-1): 
        if val1 == -1 or val2 == -1:
            self.thisptr = new Node()
        else:
            self.thisptr = new Node(val1,val2)
    

    当然,这假定 -1 是一个对函数没有用的值,您可以使用另一个值,或者如果您需要 double 的每个值都有效,那么您可能需要删除输入,获取一个 Python 对象,以便您可以使用 None 作为默认值:

    def __cinit__(self, val1=None, val2=None):
        if val1 is not None and val2 is not None:
            self.thisptr = new Node(val1, val2)
        else:
            self.thisptr = new Node()
    

    【讨论】:

    • 那么您建议如何修改代码?我不明白你的建议,我应该删除 cinit 并让 cython 为我声明它吗?
    • 请注意,这确实有一些令人不快的副作用,Node(5) 工作并使用5, -1 调用双参数构造函数;可能想检查一下。当然,基于这里的 C++ 代码使用 0 作为默认值(然后只调用两个参数的构造函数)将具有相同的效果。
    • @Dougal 假设您永远不会更改默认构造函数的功能。编辑:并添加了or 以确保设置了两个值。
    • 谢谢,现在很清楚了!这是一种解决方法还是想要的功能? (我主要在 C++ 中工作,所以这种事情看起来很奇怪)
    • 在Python中,重载函数是没有意义的(因为类型并不重要,所以除了参数的数量之外没有区别,默认值处理得更好),所以重载没有不存在。 Cython 为 cdef 函数添加了此功能,但不适用于 __cinit__() 等 Python 函数。
    猜你喜欢
    • 1970-01-01
    • 2017-01-21
    • 2021-08-14
    • 1970-01-01
    • 2022-11-12
    • 2015-10-25
    • 2011-09-13
    • 1970-01-01
    • 2014-11-21
    相关资源
    最近更新 更多