> That said, though, I'm not sure that this was even what you were asking about :)
It would be significantly more helpful if the OP had an example for the specific case where they wanted contextually defined variables to take priority over the classdict, and explained _why_ this behavior might be desirable: > > 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'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`. Describing the specific use case in detail and providing an example would also help with determining the practical value of adding the described property. I'm not certain that a property would be the best way to do it (a new optional parameter for the __prepare__ attribute might be an alternative). But before that, we have to determine whether or not the feature would have enough practical value to justify implementing in any capacity. This is of course assuming that what the OP wants doesn't already exist in some other form (if Chris's example isn't what the OP is looking for) or that it's even reasonably possible to implement in the first place. On Sat, Oct 19, 2019 at 11:39 PM Chris Angelico <ros...@gmail.com> wrote: > 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/ >
_______________________________________________ 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/BJTETDZVSPN3HDKNYO47GENO6SB56HSS/ Code of Conduct: http://python.org/psf/codeofconduct/