3

__eq__C 拡張機能として作成した Rect クラスを実装しようとすると問題が発生します。というメソッドを定義してみました__eq__が、Python がオーバーライドしているようです。

static PyObject *
Rect___eq__(Rect *self, PyObject *other)
{
    Rect *rect = (Rect *) other;
    if (self->x != rect->x || self->y != rect->y || 
            self->width != rect->width || self->height != rect->height) {
        Py_RETURN_FALSE;
    } else {
        Py_RETURN_TRUE;
    }
}

static PyMethodDef Rect_methods[] = {
    {"__eq__", (PyCFunction)Rect___eq__, METH_VARARGS,
     "Compare Rects" },
    {NULL}  /* Sentinel */
};

私が何をしても、Pythonのデフォルトは「is」動作です:

>>> a = Rect(1, 2, 3, 4)
>>> b = Rect(1, 2, 3, 4)
>>> a == b
False
>>> a == a
True
4

2 に答える 2

4

C で定義された新しい型を扱う場合、tp_richcompare を定義する必要があります。以下は、常に他のすべての型 (それ自体を除く) よりも大きく比較する型のリッチ比較の実装です。

static PyObject *
Largest_richcompare(PyObject *self, PyObject *other, int op)
{
    PyObject *result = NULL;

    if (UndefinedObject_Check(other)) {
        result = Py_NotImplemented;
    }
    else {
        switch (op) {
        case Py_LT:
            result = Py_False;
            break;
        case Py_LE:
            result = (LargestObject_Check(other)) ? Py_True : Py_False;
            break;
        case Py_EQ:
            result = (LargestObject_Check(other)) ? Py_True : Py_False;
            break;
        case Py_NE:
            result = (LargestObject_Check(other)) ? Py_False : Py_True;
            break;
        case Py_GT:
            result = (LargestObject_Check(other)) ? Py_False : Py_True;
            break;
        case Py_GE:
            result = Py_True;
            break;
        }
    }

    Py_XINCREF(result);
    return result;
}

Python 3.x を使用している場合は、次のように型オブジェクトに追加します。

(richcmpfunc)&Largest_richcompare,       /* tp_richcompare */

Python 2.x を使用している場合は、追加の手順が必要です。Python 2.x の存続期間中に豊富な比較が追加され、Python のいくつかのバージョンでは、C 拡張機能でオプションで tp_richcomare を定義できました。型が豊富な比較を実装していることを Python 2.x に通知するには、Py_TPFLAGS_HAVE_RICHCOMPARE で論理和を使用して tp_flags を変更する必要があります。

Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_RICH_COMPARE,        /* tp_flags */
于 2012-08-19T04:21:15.723 に答える
0

__cmp__PyTypeObject を宣言すると、Python 関数 (http://docs.python.org/py3k/extending/newtypes.html#object-comparison) に対応する「豊富な比較」関数のフィールドがあります(これは「リッチ」な 、 などとは対照的に__eq__、ドキュメンテーション__gt__は「非リッチ」です)。セマンティクスは別として、基本的に同じ機能を提供しますが、なぜ機能しないのかはよくわかり__eq__ません...

余談ですが、C エクステンション クラス/モジュールを書いている他の人に Cython を見てもらうことをお勧めします。Cython は依存関係を追加しますが (これはビルドの依存関係にすぎません)、エクステンションを書く際の頭痛の種がはるかに少なくなります。

于 2012-08-19T04:21:13.600 に答える