2012-04-30 5 views
15

Это более интересные явления, которые я встречал в модуле Python, который я пытаюсь понять, а не запрос на помощь (хотя решение также было бы полезно).Неисправность строк в CPython нарушена

>>> import fuzzy 
>>> s = fuzzy.Soundex(4) 
>>> a = "apple" 
>>> b = a 
>>> sdx_a = s(a) 
>>> sdx_a 
'A140' 
>>> a 
'APPLE' 
>>> b 
'APPLE' 

Да, так что fuzzy модуль полностью нарушает неизменность строк в Python. Может ли это сделать, потому что это C-расширение? И это является ошибкой в ​​CPython, а также модулем или даже угрозой безопасности?

Кроме того, может ли кто-нибудь подумать о способе обойти это поведение? Я хотел бы иметь возможность сохранить оригинальную капитализацию строки.

Cheers,

Alex

+0

Я не вижу нигде в сгенерированном C, где он мутирует строку. –

+0

@ IgnacioVazquez-Abrams: может быть, я что-то упустил, но разве он не мутировал его в '__call__' [' __pyx_f_5fuzzy_7Soundex ___ call__']? Он объявляет cdef char ptr, который он устанавливает равным результату вызова PyString_AsString, а затем изменяет содержимое. – DSM

+0

@DSM: Не в коде в Bitbucket. Я вижу только чтение от него по [строка 891] (https://bitbucket.org/yougov/fuzzy/src/c210ad2f3f68/src/fuzzy.c#cl-891). –

ответ

13

Эта ошибка была устранена back in February; обновите свою версию.

Чтобы ответить на ваш вопрос, да, существует несколько способов изменения неизменяемых типов на уровне C. Последствия безопасности неизвестны и, возможно, даже непознаваемы, на данный момент.

+0

Спасибо за этот ответ! На самом деле, я использовал easy_install для установки нечетких только три недели назад. Версия, которую он мне дает, - fuzzy-1.0-py2.7-win-amd64.egg, и именно эта версия имеет ошибку. – Alex

+0

@Alex: Они не всегда держат его в курсе событий; установить с Bitbucket. –

2

У меня нет модуля fuzzy доступны для тестирования прямо сейчас, но уже в следующем создает строку с новой идентичности:

>>> a = "hello" 
>>> b = ''.join(a) 
>>> b 
'hello' 
>>> id(a), id(b) 
(182894286096, 182894559280) 
+0

Да, это работает :) – Alex

0

Если изменения непреложная строка, это ошибка, вы можете обойти это:

s(a.upper()) 
2

Я мало что знаю о CPython, но он выглядит как в fuzzy.c, он объявляет char *cs = s, где s - это вход для __call__. Затем он мутирует cs[i], который, очевидно, будет мутировать s[i] и, следовательно, исходную строку. Это определенно ошибка с Fuzzy, и вы должны записать ее на bitbucket. Как сказал ответ Грега, использование ''.join(a) создаст новую копию.

+0

Это было подано на Bitbucket. Дважды. –

Смежные вопросы