Inserting class namespace into method scope
Duncan Booth
duncan.booth at invalid.invalid
Sat Nov 20 11:24:45 EST 2010
Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> wrote:
> But in this specific case I have reasons for wanting to avoid both of
> the normal behaviours. Do not judge me, please accept that I have a
> good reason for wanting this, or at least allow me to shoot myself in
> the foot this way *wink*. In Python 3, is there some way to get this
> unusual behaviour?
>
Sounds more like you want a mercy killing rather than just shooting in
the foot.
However, if I had taken sufficient illegal substances to want to do
this, I would decorate the function with an attribute to indicate that I
want it messed up, and then use a metaclass to create a new function
from the original one but with the class namespace in place of the
__globals__ attribute. I think you need to do it in a metaclass because
once the class is created you just have a dictproxy and you need a real
dict as the globals argument to the function constructor.
The limitations will be that the resulting method cannot access any
globals and also any changes to the class namespace won't be visible
inside the function (since the class's dictproxy is a copy of the dict).
from types import FunctionType
class WeirdClass(type):
def __new__(cls, name, bases, classdict):
for attrname, attribute in classdict.items():
if getattr(attribute, '_useclassglobals', False):
classdict[attrname] = FunctionType(attribute.__code__,
classdict, attribute.__name__,
attribute.__defaults__, attribute.__closure__)
result = type.__new__(cls, name, bases, classdict)
return result
def classglobals(f):
f._useclassglobals = True
return f
x = "outside"
class Magic(metaclass=WeirdClass):
x = "inside"
@classglobals
def method(self):
return x
m = Magic()
print(m.method()) # prints 'inside'
Magic.x = "new value"
print(m.method()) # still prints 'inside'
--
Duncan Booth http://kupuguy.blogspot.com
More information about the Python-list
mailing list