Symbols as parameters?

Alf P. Steinbach alfps at start.no
Fri Jan 22 09:36:32 EST 2010


* Steven D'Aprano:
> 
> 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?

I don't *know*, but I have a speculation. It goes like this:

   1. Perhaps first the statements in the class body are evaluated using
      a dictionary for locals, with as yet no existing class object.

   2. Perhaps that dictionary plus some other info is then passed to
      __new__ of the class' metaclass, e.g. by default 'type' as metaclass, which
      perhaps produces a class object, filling in its slots and/or __dict__ from
      the  supplied dictionary.

:-)

I'd have to read documentation and PEPs to say anything more for sure.


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

By the way, when I used 'class' to create a local scope I didn't have this 
behavior in mind, even if it might seem to be a strange coincidence. I just 
learned the above about metaclasses, if it is a correct impression, by checking 
whether the OP's declarative-like-usage code could be rescued in some way. 
Unfortunately my idea, fixing up the class' __dict__ in the metaclass, didn't 
work because the metaclass __new__ turned out to be called after, not before.


> (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.)

I agree.


Cheers,

- Alf



More information about the Python-list mailing list