小编典典

为什么在检查另一个字符串是否为空时返回True?

python

我有限的大脑无法理解为什么会这样:

>>> print '' in 'lolsome'
True

在PHP中,等效比较返回false:

var_dump(strpos('', 'lolsome'));

阅读 248

收藏
2020-12-20

共1个答案

小编典典

从文档中

对于Unicode和字符串类型,x in y当且仅当 xy 的子字符串时,才为true 。等效测试为y.find(x) != -1。注意, xy 不必是同一类型;因此,u'ab' in 'abc'将返回True
空字符串始终被视为任何其他字符串的子字符串,因此"" in "abc"将返回True

通过查看print呼叫,您正在使用2.x。

要更深入,请看一下字节码:

>>> def answer():
...   '' in 'lolsome'

>>> dis.dis(answer)
  2           0 LOAD_CONST               1 ('')
              3 LOAD_CONST               2 ('lolsome')
              6 COMPARE_OP               6 (in)
              9 POP_TOP
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE

COMPARE_OP是我们进行布尔运算并查看源代码in揭示比较发生位置的地方:

    TARGET(COMPARE_OP)
    {
        w = POP();
        v = TOP();
        if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
            /* INLINE: cmp(int, int) */
            register long a, b;
            register int res;
            a = PyInt_AS_LONG(v);
            b = PyInt_AS_LONG(w);
            switch (oparg) {
            case PyCmp_LT: res = a <  b; break;
            case PyCmp_LE: res = a <= b; break;
            case PyCmp_EQ: res = a == b; break;
            case PyCmp_NE: res = a != b; break;
            case PyCmp_GT: res = a >  b; break;
            case PyCmp_GE: res = a >= b; break;
            case PyCmp_IS: res = v == w; break;
            case PyCmp_IS_NOT: res = v != w; break;
            default: goto slow_compare;
            }
            x = res ? Py_True : Py_False;
            Py_INCREF(x);
        }
        else {
          slow_compare:
            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在同一文件中,很容易找到我们的下一个提示:

res = PySequence_Contains(w, v);

abstract.c中

{
    Py_ssize_t result;
    if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
        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);
}

为了从源头上获得帮助,我们在文档中找到了下一个功能:

objobjproc PySequenceMethods.sq_contains

此功能可能由PySequence_Contains()相同的签名使用。该插槽可以保留为 NULL
,在这种情况下,PySequence_Contains()仅遍历序列,直到找到匹配项为止。

在同一文档中进一步介绍

int PySequence_Contains(PyObject *o, PyObject *value)

确定 o是否 包含 。如果 o中 的项等于 value
,则返回1,否则返回0。出错时,返回-1。这等效于Python表达式value in o

如果''不是null,则'lolsome'可以认为该序列包含该序列。

2020-12-20