内置“in”运算符的Python源代码

时间:2012-09-03 08:05:45

标签: python c string cpython python-internals

我试图在(C)Python源代码中找到内置in运算符的实现。我在内置函数源代码bltinmodule.c中搜索过,但找不到此运算符的实现。我在哪里可以找到这个实现?

我的目标是通过扩展此搜索的不同C实现来改进Python中的子字符串搜索,尽管我不确定Python是否已经使用了我的想法。

1 个答案:

答案 0 :(得分:31)

要查找任何 python运算符的实现,首先要使用dis.dis function找出Python为其生成的字节码:

>>> dis.dis("'0' in ()")
  1           0 LOAD_CONST               0 ('0')
              2 LOAD_CONST               1 (())
              4 COMPARE_OP               6 (in)
              6 RETURN_VALUE

in运算符变为COMPARE_OP字节代码。现在,您可以在Python/ceval.c中的Python评估循环中跟踪如何处理此操作码:

TARGET(COMPARE_OP)
    PyObject *right = POP();
    PyObject *left = TOP();
    PyObject *res = cmp_outcome(oparg, left, right);
    Py_DECREF(left);
    Py_DECREF(right);
    SET_TOP(res);
    if (res == NULL)
        goto error;
    PREDICT(POP_JUMP_IF_FALSE);
    PREDICT(POP_JUMP_IF_TRUE);
    DISPATCH();

cmp_outcome()defined in the same filein运算符是其中一个开关:

case PyCmp_IN:
    res = PySequence_Contains(w, v);
    if (res < 0)
         return NULL;
    break;

快速grep向我们展示了Objects/abstract.c中<{1}}的定义{/ 1}}:

PySequence_Contains
因此,对于Python C对象,

int PySequence_Contains(PyObject *seq, PyObject *ob) { Py_ssize_t result; PySequenceMethods *sqm = seq->ob_type->tp_as_sequence; if (sqm != NULL && sqm->sq_contains != NULL) return (*sqm->sq_contains)(seq, ob); result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS); return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); } 使用sq_contains slot on the Sequence object structure或迭代搜索。

对于Python 3 Unicode字符串对象,此插槽实现为PyUnicode_Contains in Objects/unicodeobject.c,在Python 2中,您还要查看string_contains in Objects/stringobject.c。基本上只是在Objects /子目录中为PySequence_Contains grep,用于不同Python类型的各种实现。

对于通用python对象,值得注意的是Objects/typeobject.c将此问题推迟到自定义类的sq_contains方法,如果这样定义的话。