3

なぜa is Noneより速く動作するのかという答えを検索しますa == None。私はこのコードを使用して時間を測定します:

>>> timeit.timeit("1 is None", number=10000000)
0.4035069934390217
>>> timeit.timeit("1 == None", number=10000000)
0.8190256083633187

ドキュメントには、それは同等の機能を持ち、a is b同等の機能を持っていると書かれています。では、なぜ関数がより高速なのですか?is_(a, b)a == beq(a, b)is_eq

is_()オブジェクトの識別子のみを比較し、 eq()「詳細な比較」を行ういくつかの記事を読みました。しかし、私はこの情報をドキュメントで見つけることができません。この情報は正しいですか?これについてもっと読むことができる場所はどこですか?

4

2 に答える 2

9

同一性 ( ) のテストisは、単純なポインター比較 (2 つの値が同じオブジェクトかどうか) と同じです。

同等性をテストするには、それ以上の作業が必要です。たとえば、リストの場合、何かが等しいかどうかをテストするか、最短のリストのすべての要素がテストされるまで、両方のリストのすべての要素が等しいかどうかをテストする必要があります。

2 つの演算子は、テスト対象が大きく異なることに注意してください。

>>> lsta = []
>>> lstb = lsta
>>> lsta is listb
True
>>> lstc = []
>>> lsta is listc
False
>>> lsta == listc
True

2 つのオブジェクトが等しいからといって、それらが同じオブジェクトであるとは限りません。is後者のテスト。

于 2013-01-31T17:39:26.930 に答える
2

is比較 ( 、==<=など)を実装する Python ソース コードを次に示します。

Python/ceval.c:4501

static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
    int res = 0;
    switch (op) {
    case PyCmp_IS:
        res = (v == w);
        break;
    ...
    default:
        return PyObject_RichCompare(v, w, op);

isは、単純な C ポインター比較という 1 行のコードで実装されます。一部の Python プリミティブは、これに従って等しいと比較されます (interning のため、または 、 、 のようなシングルトンであるTrueためFalse) None

一方、ヘルパー関数で実装されている をeq使用します。PyObject_RichComparedo_richcompare

richcmpfunc f;
PyObject *res;
int checked_reverse_op = 0;

if (v->ob_type != w->ob_type &&
    PyType_IsSubtype(w->ob_type, v->ob_type) &&
    (f = w->ob_type->tp_richcompare) != NULL) {
    checked_reverse_op = 1;
    res = (*f)(w, v, _Py_SwappedOp[op]);
    if (res != Py_NotImplemented)
        return res;
    Py_DECREF(res);
}
if ((f = v->ob_type->tp_richcompare) != NULL) {
    res = (*f)(v, w, op);
    if (res != Py_NotImplemented)
        return res;
    Py_DECREF(res);
}
if (!checked_reverse_op && (f = w->ob_type->tp_richcompare) != NULL) {
    res = (*f)(w, v, _Py_SwappedOp[op]);
    if (res != Py_NotImplemented)
        return res;
    Py_DECREF(res);
}

これにより、引数の型がチェック__eq__され、答えを決定する前に複数の比較関数 (メソッド) が試行される可能性があります。比較メソッドは無制限の作業を行う可能性があります (たとえばlist.__eq__、リストの各要素をおそらく再帰的にチェックする必要があります) が、単純な の場合でもx == None、型チェックとすべての余分な作業により、 に比べて実際の速度が低下しisます。

于 2013-01-31T17:52:00.947 に答える