2017-02-21 20 views
6

После просмотра this question и its duplicate вопрос остался для меня.Python Interpreter String Оптимизация пула

я получаю то, что is и == делать и почему, если я бегу

a = "ab" 
b = "ab" 

a == b 

я True. Вопрос здесь будет ПОЧЕМУ это происходит:

a = "ab" 
b = "ab" 
a is b # Returns True 

Так что я сделал свое исследование, и я нашел this. Ответ говорит, что интерпретатор Python использует пул строк. Поэтому, если он видит, что две строки одинаковы, он присваивает то же самое id новому для оптимизации.

До сих пор все в порядке и ответа. Мой реальный вопрос - почему этот пул происходит только для некоторых строк. Вот пример:

a = "ab" 
b = "ab" 
a is b # Returns True, as expected knowing Interpreter uses string pooling 

a = "a_b" 
b = "a_b" 
a is b # Returns True, again, as expected knowing Interpreter uses string pooling 

a = "a b" 
b = "a b" 
a is b # Returns False, why?? 

a = "a-b" 
b = "a-b" 
a is b # Returns False, WHY?? 

Так что, похоже, для некоторых символов пул строк не работает. Я использовал Python 2.7.6 для этих примеров, поэтому я думал, что это будет исправлено в Python 3. Но после того, как вы попытаетесь использовать те же примеры в Python 3, появятся те же результаты.

Вопрос: Почему оптимизатор строк не оптимизирован для этих примеров? Не лучше ли Python оптимизировать это?


Edit: Если я бегу "a b" is "a b" возвращается True. Вопрос в том, почему с помощью переменных он возвращает False для некоторых символов, но True для других.

+0

питон 3.4.4 окна: '>>> а = "абы", б = "абы" >>> а есть б true' –

+0

@ Жан-FrançoisFabre python3.4.3 на Ubuntu возвращает' false' –

+0

python 3.5 windows ''ab' is 'a b'' оценивает' True' –

ответ

4

Ваш вопрос является дубликатом более общий вопрос «When does python choose to intern a string», то correct answer, к которой является то, что строка интернирование является реализация конкретных.

Интерпретация строк в CPython 2.7.7 описана очень хорошо в этой статье: The internals of Python string interning. Информация в нем позволяет объяснить ваши примеры.

Причина, по которой строки "ab" и "a_b" интернированы, в то время как "a b" и "a-b" не являются, в том, что прежний вид, как идентификаторы питона и последний не делают.

Естественно, интернирование каждой строки приведет к затратам времени исполнения. Поэтому интерпретатор должен решить, стоит ли задавать строку. Поскольку имена идентификаторов, используемых в программе python, встроены в байт-код программы как строки, строки, подобные идентификаторам, имеют более высокий шанс получить выгоду от интернирования.

Короткий отрывок из приведенной выше статье:

Функция all_name_chars исключает строки, которые не состоят из ASCII букв, цифр или символов подчеркивания, т.е.строки выглядит как идентификаторы:

#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; 
} 

Со всеми этими объяснениями в виду, мы теперь понимаем, почему 'foo!' is 'foo!' вычисляется в False тогда 'foo' is 'foo' вычисляется в True.

+0

Это довольно аккуратно! Благодаря! –

+0

Статья, на которую вы ссылаетесь, отличная, но речь идет о Python 2.7, что важно, поскольку это детали реализации. В любом случае, я думаю, что это обман: http://stackoverflow.com/questions/10622472/when-does-python-choose-to-intern-a-string –

+0

@Chris_Rands Согласитесь. Я обновил ответ и добавил свой голос, чтобы закрыть вопрос как обман. – Leon