2012-04-30 11 views
15

Jest to bardziej "interesujące" zjawisko, które napotkałem w module Pythona, który próbuję zrozumieć, niż prośbę o pomoc (choć byłoby również przydatne rozwiązanie).Niezmienność ciągów w CPython naruszone

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

Tak więc moduł fuzzy całkowicie narusza niezmienność ciągi w Pythonie. Czy jest to możliwe, ponieważ jest to rozszerzenie C? Czy stanowi to błąd w CPython, a także w module, a nawet w ryzyku bezpieczeństwa?

Czy ktoś może wymyślić sposób na obejście tego zachowania? Chciałbym móc zachować oryginalną wielkość liter w łańcuchu.

Cheers,

Alex

+0

Nie widzę nigdzie w wygenerowanym C, w którym mutuje ciąg znaków. –

+0

@ IgnacioVazquez-Abrams: może czegoś brakuje, ale czy nie zmienia tego w '__call__' [' __pyx_f_5fuzzy_7Soundex ___ call__']? Deklaruje cdef char ptr, który ustawia jako równy wynikowi wywołania PyString_AsString, a następnie modyfikuje zawartość. – DSM

+0

@DSM: Nie w kodzie w Bitbucket. Widzę tylko odczyty z niego, w [linii 891] (https://bitbucket.org/yougov/fuzzy/src/c210ad2f3f68/src/fuzzy.c#cl-891). –

Odpowiedz

13

Ten błąd został rozwiązany back in February; zaktualizuj swoją wersję.

Aby odpowiedzieć na pytanie, tak, istnieje kilka sposobów modyfikacji typów niezmiennych na poziomie C. Implikacje związane z bezpieczeństwem są w tym momencie nieznane i być może nawet niepoznane.

+0

Dzięki za tę odpowiedź! Właściwie użyłem easy_install do instalacji fuzzy zaledwie trzy tygodnie temu. Wersja, którą mi podaję, to fuzzy-1.0-py2.7-win-amd64.egg i ta wersja ma błąd. – Alex

+0

@Alex: Nie zawsze są tam na bieżąco; zainstalować z Bitbucket. –

2

nie mam moduł fuzzy dostępne przetestować teraz, ale dodaje tworzy ciąg z nową tożsamością:

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

Tak, to działa :) – Alex

0

Jeśli zmienia niezmienny ciąg, to błąd, możesz obejść to przez:

s(a.upper()) 
2

Nie wiem zbyt wiele na temat CPython, ale wygląda na to, że w fuzzy.c deklaruje char *cs = s, gdzie s jest wejściem do __call__. Następnie mutuje on cs[i], co oczywiście zmutuje s[i], a zatem oryginalny ciąg. Jest to z pewnością błąd w Fuzzy i powinieneś go złożyć na bitbucket. Zgodnie z odpowiedzią Grega, użycie ''.join(a) spowoduje utworzenie nowej kopii.

+0

Zostało złożone na Bitbucket. Dwa razy. –

Powiązane problemy