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