Overriding "__setattr__" of a module - possible?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Thu Jun 17 05:29:04 EDT 2010


En Thu, 17 Jun 2010 04:52:48 -0300, Alf P. Steinbach <alfps at start.no>  
escribió:

> * Gabriel Genellina, on 17.06.2010 09:25:
>> En Wed, 16 Jun 2010 19:56:39 -0300, Ian Kelly <ian.g.kelly at gmail.com>
>> escribió:
>>
>>> On Wed, Jun 16, 2010 at 3:38 PM, John Nagle <nagle at animats.com> wrote:
>>>> That just leaves things in a state where even "sys" and "import"
>>>> are undefined.
>>>
>>> Say what? It works fine for me.
>>>
>>>>>> import proxy_mod
>>>>>> proxy_mod.f()
>>> 1
>>>>>> proxy_mod.a = 2
>>> setting a=2
>>>>>> proxy_mod.f()
>>> 2
>>>>>> proxy_mod.sys
>>> <module 'sys' (built-in)>
>>
>> It *mostly* works, but not always. Try this function:
>>
>> def g(x):
>> global a
>> print 'global a -> ', x
>> a = x
>>
>> py> import fake # ModuleProxy stuff
>> py> fake.f()
>> 1
>> py> fake.a = 3
>> setting a=3
>> py> fake.f()
>> 3
>> py> fake.g(8)
>> global a -> 8
>> py> fake.f()
>> 8
>> py> fake.a
>> 8
>>
>> Note the fake.g(8) call: __setattr__ wasn't called.
>> If the OP wants to trace assignments to global variables, this becomes a
>> problem.
>>
>> A function defined in a module holds a reference to the module's
>> __dict__ in its func_globals attribute. Getting and setting global
>> variables goes directly to this dictionary, and does not use the module
>> object at all.
>>
>> Even worse, the LOAD_GLOBAL/STORE_GLOBAL opcodes (which implement
>> getting and setting global variables) assume func_globals is a true
>> dictionary and bypass any overriden __getitem__/__setitem__ methods (an
>> optimization, surely). I'm afraid it will be hard to intercept global
>> variable usage in these circumstances.
>
> Great exposition.
>
> But who would have thunk that Python *isn't dynamic enough*? :-)

Yep... There are other examples too (e.g. the print statement in 2.x  
bypasses sys.stdout.write; see also a recent thread "Which objects are  
expanded by double-star ** operator?")

Most of them seem to be speed optimizations, some might be considered  
subtle bugs. But in this case (global variable references) speed is so  
critical than even the dict lookup is inlined; the code in ceval.c says:

/* Inline the PyDict_GetItem() calls.
WARNING: this is an extreme speed hack.
Do not try this at home. */

Python is dynamic but not so much as to make it crawl like a snail...

-- 
Gabriel Genellina




More information about the Python-list mailing list