[python] metoda str

Hynek Fabian hynek.fabian na firma.seznam.cz
Středa Listopad 3 18:31:30 CET 2010


> Ehm, ne, o to my nešlo, šlo mi o přepsání __builtin__ třídy str tak abych
> přepsal chování instancí Stringu.

Tak jak to píšes ale na builtin nesáhneš!
"class str(str)" ti udělá objekt jménem str v LOKÁLNÍM jmenném prostoru, 
nikoliv v builtins. V tomto kontextu tvůj lokální jmenný prostor je globální 
prostor modulu, ergo v jiných modulech zůstane str nezměněn.
Sáhnout do builtins je možné a prosté:

class MyStr(str): pass
__builtins__.str = MyStr

a je to. Všimni si že nemusíš mást budoucí generace tím, že to pojmenuješ 
stejně - konstruktor je sice viditelný pod jménem 'str', ale 
__class__.__name__ hotového objektu bude MyStr. Metody, potomci, etc. se bude 
odvolávat na objekt MyStr, pouze "uživatelé" jména 'str' potřebují znát nový 
objekt pod starým jménem.

Leč, rychlý experiment ukáže, že interpret nekonstruuje řetězcové literály 
pomocí __builtins__.str, ale drží někde vlastní referenci na StringType. Řekl 
bych, že je to dobře, hrabání se v builtins je nejvetší prasárna nad jakou by 
se ještě dalo přivřít oko :-)
Teoreticky bys mohl změnit chování zabudovaných řetězců hrabáním se přímo v 
jejich třídě:
"a".__class__.asx = "asx"
Změna přes referenci na třídu se okamžitě projeví u všech existujících 
instancí, potomků etc. Předefinováním metody __new__() bys mohl dokonce 
dosáhnout aby konstrukce objektu vracela instanci objektu úplně jiného typu, 
napříkald MyStr...
Na(ne)štěstí taková konstrukce nefunguje přímo na zabudované objekty,   
protože ty nemají vlastní jmenný prostor ale jen neměnitelné sloty.
Běžně to ničemu nevadí, protože jmenný prostor si můžeš opatřit prostě tím,  
že podědíš, čímž jsme zpátky u nevrtání se ve střevech interpretru :)

Jiné řešení které mě napadá - projít rekurzivně zadaný jmenný prostor a 
instance StringType nenápadně proměnit. Není to sice tolik "automagické", ale 
taky mnohem bezpečnější.


Další informace o konferenci Python