How safe is modifying locals()?

Paul Paterson paulpaterson at
Mon Jul 28 02:20:48 CEST 2003

Bengt Richter wrote:

> On Sun, 27 Jul 2003 04:51:11 GMT, Paul Paterson <paulpaterson at> wrote:
> [...]
>>To my eye, the [:] or [0] spelling of this makes the code look more 
>>complex than necessary, but I think you are on to something because if 
>>you spell it,
>>def change(x, y):
>>   x = 'new x'
>>   y.update('new y')
> For a general pointer, ISTM you want to be able to dereference it for both getting and setting.
> The [:] or [0] syntax gets you that, and you could do it with p() for getting and p(val) for setting,
> or p.getval() and p.update(), but all these get clumsy when you want to use the "pointer" on
> both sides of an assignment statement, e.g.,
>     p.update(p.getval()+' added text for target')
> where you could write more readably (IMO),
>     p.value = p.value + 'added text for target'

Yes, this feels right. Visually you have only one element to recognize 
(p.value) which makes it not much more complex than the original code. A 
single search and replace could also get rid of the pointer semantics if 
it was later decided that they were not required.

> or
>     p.v += 'added text for target'
> Below is a class PNS that lets you spell as immediately above, using .value
> (and .v for concise use) bound to a property that implements the accessing of
> what's pointed/referred to. I gave it a somewhat informative __repr__ method also,
> so the test prints better. As you will note, this is now separate from any particular
> name space. Any object that supports getattr and/or setattr can be used. I also
> threw in a permissions parameter to control read/write/delete. See nsother and math
> in examples. Note also that a pointer may point to another pointer, allowing cascaded
> dereferencing spelled p.v.v etc.
>>with the relevant changes to the Ptr class then it could certainly grow 
>>on me. The things I like are,
>>- no new variable names in the 'change' function so it looks similar to 
>>the original code
>>- the mechanism for propogating changes to the caller scope is explicit
>>- 'y' can be passed on to another function if needed and things are 
>>still clear
>>def change(x, y):
>>    x = 'new x'
>>    change2(y)
>>def change2(y):
>>    y.update('deep change in y')
> If you use PNS, that will be spelled
>  def change(x, y):
>       x = 'new x'
>       change2(y)
>  def change2(y):
>       y.value = 'deep change in y'

Looks good!

<snip PNS code + tests>

I like this a lot - it is much clearer than a bare namespace when you 
start passing these things around. In fact, I don't think the namespace 
can actually work in the change/change2 example above. Consider,

def change(x, y):
    x = 'new x'

def change2(z):
    z = 'deep change to y'

Using the bare namespace you would have to pass ns to 'change' and then 
address 'y' as ns.y ... but then when you pass it to change2 it has to 
be called z, but you can't call it ns.z ...

Using the pointer system (or sisters?!) you pass the "pointer" and then 
always refer to it as localname.value. Neat!

I'm not sure if I would recommend this in general but for my application 
it seems to be a nice approach.

>>Thanks for these thoughts and the time it took to post them, they really 
>>made me think! (I mean that in a good way, of course ;) )
> You're welcome. Hope this adds another useful angle.

Absolutely! Thanks again.


More information about the Python-list mailing list