L'interprete Python memorizza alcune stringhe in base a determinati criteri, la prima stringa abc
viene memorizzata nella cache e utilizzata per entrambi, mentre la seconda non lo è. Lo stesso vale per i piccoli interi da -5
a 256
.
Poiché le stringhe sono internati/assegnazione di cache a
e b
-"abc"
rende a
e b
punto agli stessi oggetti in memoria in modo da utilizzare is
, che verifica se due oggetti sono in realtà lo stesso oggetto, restituisce True
.
La seconda stringa abc abc
non viene memorizzata nella cache in modo che siano due oggetti completamente diverso in memoria controllo d'identità in modo utilizzando is
rendimenti False
. Questa volta a
è nonb
. Entrambi puntano a oggetti diversi nella memoria.
In [43]: a = "abc" # python caches abc
In [44]: b = "abc" # it reuses the object when assigning to b
In [45]: id(a)
Out[45]: 139806825858808 # same id's, same object in memory
In [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 objects
Out[50]: 139806688801208
I criteri per le stringhe di caching è se la stringa ha solo lettere, underscores e numeri nella stringa Quindi nel tuo caso lo spazio non soddisfa i criteri.
Utilizzando l'interprete esiste un caso in cui si può finire per puntare allo stesso oggetto anche quando la stringa non soddisfa i criteri di cui sopra, più assegnazioni.
In [51]: a,b = 'abc abc','abc abc'
In [52]: id(a)
Out[52]: 139806688801768
In [53]: id(b)
Out[53]: 139806688801768
In [54]: a is b
Out[54]: True
Guardando codeobject.c source per decidere i criteri che vediamo NAME_CHARS
decide che cosa può essere internato:
#define NAME_CHARS \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
static int
all_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;
}
una stringa di lunghezza 0 o 1 sarà sempre condivisa come si può vedere nella funzione PyString_FromStringAndSize
nel stringobject.c origine.
/* share short strings */
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;
}
Non direttamente legati alla domanda, ma per chi fosse interessato PyCode_New
anche dalla fonte codeobject.c
mostra come più stringhe sono internati quando si costruisce una codeobject una volta le corde soddisfino i criteri in all_name_chars
.
PyCodeObject *
PyCode_New(int argcount, int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, int firstlineno,
PyObject *lnotab)
{
PyCodeObject *co;
Py_ssize_t i;
/* Check argument types */
if (argcount < 0 || nlocals < 0 ||
code == 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(code)) {
PyErr_BadInternalCall();
return NULL;
}
intern_strings(names);
intern_strings(varnames);
intern_strings(freevars);
intern_strings(cellvars);
/* Intern selected string constants */
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));
}
Questa risposta si basa su semplici compiti utilizzando l'interprete CPython, per quanto riguarda l'internamento in relazione a funzioni o qualsiasi altra funzionalità al di fuori di semplici compiti, che non è stato chiesto nemmeno risposto.
Se qualcuno con una maggiore comprensione del codice c ha qualcosa da aggiungere sentitevi liberi di modificare.
C'è una spiegazione molto più approfondita here dell'intera stringa interning.
Questa domanda è formulata in modo diverso, ma le risposte alle altre domande funzionano qui, poiché la chiave sta riconoscendo cosa fa 'is' e come differisce da' == '. – DSM
C'è stato un commento che è stato cancellato facendo riferimento alla differenza tra "è" e "==". È questo il tuo problema, o sei curioso di sapere perché le stringhe hanno la stessa identità se non c'è spazio, ma hanno identità diverse quando c'è un carattere spaziale ... Altri caratteri non stampabili rendono anche le identità diverse. – hft
Ho chiesto NULLA come == o la differenza tra == ed è, sry – midkin