为什么空格会影响相等字符串的身份比较?

为什么空格会影响相等字符串的身份比较?,第1张

为什么空格会影响相等字符串的身份比较?

python解释器根据某些条件缓存一些字符串,第一个

abc
字符串被缓存并用于两者,而第二个则不。从in
-5
到int的小整数也是一样
256

由于字符串被扣留/高速缓存分配

a
b
"abc"
品牌
a
b
在存储器中指向同一对象,以便使用
is
,它检查是否两个对象实际上是相同的对象,返回
True

第二个字符串

abc abc
不会被缓存,因此它们是内存中的两个完全不同的对象,因此使用
is
return进行身份检查
False
。这一次
a

不是
b
。它们都指向内存中的不同对象。

In [43]: a = "abc" # python caches abcIn [44]: b = "abc" # it reuses the object when assigning to bIn [45]: id(a)Out[45]: 139806825858808    # same id's, same object in memoryIn [46]: id(b)Out[46]: 139806825858808    In [47]: a = 'abc abc'   # not cached  In [48]: id(a)Out[48]: 139806688800984    In [49]: b = 'abc abc'    In [50]: id(b)         # different id's different objectsOut[50]: 139806688801208

缓存字符串的条件是:如果字符串中仅包含 字母下划线数字 ,则您的空间不符合条件。

使用解释器,在一种情况下,即使字符串不满足上述条件,您仍然可以指向同一对象,即多次分配。

In [51]: a,b  = 'abc abc','abc abc'In [52]: id(a)Out[52]: 139806688801768In [53]: id(b)Out[53]: 139806688801768In [54]: a is bOut[54]: True

查看
preobject.c源代码来确定我们所看到的标准,从而

NAME_CHARS
确定可以进行中断的内容:

#define NAME_CHARS     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"static intall_name_chars(unsigned char *s){    static char ok_name_char[256];    static unsigned char *name_chars = (unsigned char *)NAME_CHARS;    if (ok_name_char[*name_chars] == 0) {        unsigned char *p;        for (p = name_chars; *p; p++) ok_name_char[*p] = 1;    }    while (*s) {        if (ok_name_char[*s++] == 0) return 0;    }    return 1;}

正如我们

PyString_FromStringAndSize
在stringobject.c源代码中的函数中看到的那样,长度为0或1的字符串将始终被共享。

    if (size == 0) {        PyObject *t = (PyObject *)op;        PyString_InternInPlace(&t);        op = (PyStringObject *)t;        nullstring = op;        Py_INCREF(op);    } else if (size == 1 && str != NULL) {        PyObject *t = (PyObject *)op;        PyString_InternInPlace(&t);        op = (PyStringObject *)t;        characters[*str & UCHAR_MAX] = op;        Py_INCREF(op);    }    return (PyObject *) op;}

与问题没有直接关系,但对于感兴趣的人

PyCode_New
也从
preobject.c
源头开始显示,一旦字符串满足中的条件,在构建代码对象时如何插入更多字符串
all_name_chars

PyCodeObject *PyCode_New(int argcount, int nlocals, int stacksize, int flags,       PyObject *pre, PyObject *consts, PyObject *names,       PyObject *varnames, PyObject *freevars, PyObject *cellvars,       PyObject *filename, PyObject *name, int firstlineno,       PyObject *lnotab){    PyCodeObject *co;    Py_ssize_t i;        if (argcount < 0 || nlocals < 0 ||        pre == NULL ||        consts == NULL || !PyTuple_Check(consts) ||        names == NULL || !PyTuple_Check(names) ||        varnames == NULL || !PyTuple_Check(varnames) ||        freevars == NULL || !PyTuple_Check(freevars) ||        cellvars == NULL || !PyTuple_Check(cellvars) ||        name == NULL || !PyString_Check(name) ||        filename == NULL || !PyString_Check(filename) ||        lnotab == NULL || !PyString_Check(lnotab) ||        !PyObject_CheckReadBuffer(pre)) {        PyErr_BadInternalCall();        return NULL;    }    intern_strings(names);    intern_strings(varnames);    intern_strings(freevars);    intern_strings(cellvars);        for (i = PyTuple_Size(consts); --i >= 0; ) {        PyObject *v = PyTuple_GetItem(consts, i);        if (!PyString_Check(v)) continue;        if (!all_name_chars((unsigned char *)PyString_AS_STRING(v))) continue;        PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));    }

这个答案是基于使用cpython解释器的简单分配的,只要不问或未回答,就与除简单分配之外的功能或任何其他功能的关联而言。

如果对C代码有更深入的了解的人可以添加任何内容,请随时进行编辑。

还有一个更详尽的解释这里的整串实习的。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5643604.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-16

发表评论

登录后才能评论

评论列表(0条)

    保存