Aby znaleźć realizację dowolny operatora Pythona, najpierw dowiedzieć się, jakie kodu bajtowego Python generuje dla niej, używając dis.dis
function:
>>> def inop():
... '0' in []
...
>>> dis.dis(inop)
2 0 LOAD_CONST 1 ('0')
3 LOAD_CONST 2 (())
6 COMPARE_OP 6 (in)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
Operator in
staje się kod COMPARE_OP
bajt. Teraz można śledzić to w pętli oceny w Python/ceval.c
:
TARGET(COMPARE_OP)
w = POP();
v = TOP();
x = cmp_outcome(oparg, v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x == NULL) break;
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
cmp_outcome()
jest zdefiniowana w tym samym pliku, a operator in
jest jeden z przełączników:
case PyCmp_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
break;
Szybkie grep pokazuje nam, gdzie PySequence_Contains
został zdefiniowany w 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
sposób wykorzystuje sq_contains
slot on the Sequence object structure lub wyszukiwanie iteracyjne w przypadku obiektów Python C.
Dla obiektów napisanych w python 3 unicode, ten slot jest zaimplementowany jako PyUnicode_Contains
in Objects/unicodeobject.c, w Pythonie 2 również chcesz sprawdzić string_contains
in Objects/stringobject.c. Zasadniczo po prostu grep dla sq_contains
w podkatalogu Obiekty/podkatalogu dla różnych implementacji według różnych typów Pythona.
Dla ogólnych obiektów python warto zauważyć, że Objects/typeobject.c odrzuca to do metody __contains__
na niestandardowych klasach, jeśli tak zdefiniowano.
Dzięki za odpowiedź – Michael
@Michael: rozważ zaakceptowanie tej odpowiedzi, ponieważ jest ona o wiele bardziej pomocna niż moja. – georg
@ thg435: masz rację, +1 odpowiedź została przyjęta – Michael