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/

Reply via email to