* 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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to