要找到 任何 python运算符的实现,请首先使用dis.dis
函数找出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评估循环中跟踪如何处理此操作码Python/ceval.c
:
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()
是在相同的文件中定义,并且in
操作者是开关中的一个:
case PyCmp_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
break;
快速grep向我们显示了PySequence_Contains
在Objects / abstract.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);
}
PySequence_Contains
因此,对于Python C对象,请使用sq_contains
Sequence对象结构上的插槽或其他方式进行迭代搜索。
对于Python 3 Unicode字符串对象,此插槽的实现方式PyUnicode_Contains
与Objects / unicodeobject.c相同,在Python 2中,您还想string_contains
在Objects / stringobject.c中检出。基本上sq_contains
,对于不同Python类型的各种实现,仅在Objects /子目录中使用grep即可。
对于通用python对象,有趣的是注意到Objects / typeobject.c将其推迟到__contains__
自定义类的方法(如果已定义)。