On Sun, Oct 20, 2019 at 1:58 PM Steve Jorgensen <ste...@stevej.name> wrote: > > When using a custom classdict to implement a DSL or use in the body of a > class definition, from what I can tell by experiment, the classdict takes > priority, and the surrounding context is only referenced if trying to get an > item from the classdict raises `KeyError`. > > There is at least one case in which I would like to do the reverse, and have > the classdict be secondary to (masked by) any variables defined in the > context surrounding the execution of the class body. > > I have been able to at least unmask builtins by having the classdict object > first try to get a result from `__builtins__` and then fall back to itself. > Also, in the actual class body, declaring a variable as `global` seems to be > a workaround for global variables, but that has to be done explicitly in the > body of any subclass that needs it. Also, that does not handle non-globals in > its surrounding context. > > I'm not sure what the best way to deal with this would be, but my first > thought is to maybe have a property that can be set on the metaclass type > such as `metacls.relictant_classdict = True`. >
Not entirely sure I follow here; are you talking about unadorned names during the execution of the class body itself, or the way attribute lookup is done on the resulting object? If you want to be able to mess with attribute lookup even when the attribute does exist, __getattribute__ is your friend: https://docs.python.org/3/reference/datamodel.html#object.__getattribute__ For changing the behaviour of class body execution, it's a bit harder. Do you actually need the class members to be available as unadorned names, but such that the surrounding context takes precedence? That could be awkward, since there's no way (as far as I know) to get a "hook" whenever NameError would have been raised. But you can return any dict-like object from the metaclass's __prepare__ method, and if its __getitem__ and __setitem__ are disconnected, you could get the effect you want. Here's one possibility that gets kinda close: class BlackBox(dict): def __getitem__(self, item): if item == "v": return self raise KeyError __getattr__ = dict.__getitem__ class Meta(type): @classmethod def __prepare__(meta, cls, bases): return BlackBox() var = "global" class Demo(metaclass=Meta): var = "local" print("var =", var) print("v.var =", v.var) Accessing local names can be done with the "v." prefix, global names are directly accessible, but missing globals won't be looked up locally. That said, though, I'm not sure that this was even what you were asking about :) ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/64VR434UDBIEJD3JYSLS3V7BPDTT36U3/ Code of Conduct: http://python.org/psf/codeofconduct/