Symbols as parameters?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Jan 22 13:55:40 CET 2010


On Fri, 22 Jan 2010 09:29:18 +0100, Alf P. Steinbach wrote:

> But have you tested this within a function or class, which is what the
> use of "locals" implies?
> 
> The reason that I ask is that in the documentation of locals() it says
> this:
> 
>    Note
>    The contents of this dictionary should not be modified; changes may
>    not affect the values of local variables used by the interpreter.
> 
> (There's no such note for 'globals').
> 
> I have to admit that I was afraid to post this question since my
> experience in [comp.lang.python] is that when some technical error is
> pointed out by me, then most often the person starts a personal attack
> and credibility attack, injecting all kinds of noise --  actually that
> happened yet again as I was writing this response to you! But, I figure
> one shouldn't give up one humanity just because of one group where that
> happens regularly. I'm sort of counting on you to prove that there are,
> counting myself and one other, and perhaps now you, at least three
> persons here who are happy for technical corrections from me.

I've previously said, and I'll say it again, that you do bring much of 
value to this community, tech-wise. Shame that it comes along with such a 
thin skin. It's getting so that I often find myself afraid to disagree 
with anything you say lest you accuse me of lying again.


> Or, perhaps there's some aspect of locals(), e.g. in the context of
> decorators, that I don't know about and can now learn. :-)

No, you got it spot on. Not to discourage you, but you're at least the 
third person who pointed this out in this thread.

One implementation-specific trick is that modifying locals does actually 
work inside a class definition (at least in Python 2.5):

>>> class Foo(object):
...     x = 1
...     print locals()
...     locals()['x'] = 2
...
{'x': 1, '__module__': '__main__'}
>>> Foo.x
2

But it doesn't work in functions. That is because the local variables in 
CPython functions aren't stored in a dict, for efficiency reasons, so 
locals() makes a copy of those variables rather than returning the actual 
dict used as a namespace.

This suggests we can cause locals() to malfunction in a class too, by 
using slots, since slotted attributes aren't stored in a dictionary. 
That's what I would predict, but alas I'm wrong:

>>> class Foo(object):
...     __slots__ = 'x'
...     x = 1
...     print locals()
...     locals()['x'] = 2
...
{'x': 1, '__module__': '__main__', '__slots__': 'x'}
>>> Foo.x
2

So I don't understand why this works. Anyone know?

Bottom line is, modifying locals() is not supported as a language 
feature. If it works, it's an accident.

(Since Python can't guarantee that modifications to locals() will take, I 
wonder whether it would be better to ensure that they *never* take, 
rather than sometimes. It would only require locals() to return a copy of 
the dict, a shallow copy would probably do.)


-- 
Steven



More information about the Python-list mailing list