0

I want to add static methods to a class thanks to a metaclass. Is this possible? Here is what I tried:

from django.conf import settings
import six

class Setting(object):
    def __init__(self, name=None, default=None):
        self.name = name
        self.default = default


class Metaclass(type):
    def __new__(mcs, cls, bases, dct):
        new_attr = {}
        for name, val in dct.items():
            if isinstance(val, Setting):
                # populate name
                if val.name is None:
                    val.name = name.upper()
                # add a static getter
                new_attr['get_%s' % name] = staticmethod(lambda: getattr(
                    django_settings, val.name, val.default))
            new_attr[name] = val

        return super(Metaclass, mcs).__new__(mcs, cls, bases, new_attr)


class AppSettings(six.with_metaclass(Metaclass)):
    pass

I also tried to defer the assignment of the static getter after the class is created, like:

new_class = super(Metaclass, mcs).__new__(mcs, cls, bases, {})
# loop on dct, memorize what methods to set
for name, method in deferred_methods.items():
    setattr(new_class, name, method)
return new_class

It seems to be working, but when I run some tests with a subclass of AppSettings and some settings in it, then everything is mixed up. Behaviour changes everytime I re-run the tests. It this due to the use of lambdas?

pawamoy
  • 3,382
  • 1
  • 26
  • 44
  • 1
    You are creating `lambda` function objects with a closure. That closure is dereferenced when you *call* the function, not when you define it. See the duplicate. – Martijn Pieters Mar 29 '17 at 13:22
  • Well, this is what I want. I specifically want it to be dereferenced when I call it rather than immediately at definition. My question here is more "How to add static methods from a metaclass?" I just tried to give a simplified example of what I want. But I see what you mean, the random behaviour is due to "free variables" being set from parent scope at execution, not definition. – pawamoy Mar 29 '17 at 13:25
  • This has nothing to do with metaclasses however, or staticmethods. It's everything to do with how closures work. The duplicate lists several options. – Martijn Pieters Mar 29 '17 at 13:26
  • Okay thanks I'll fix the closue issue and edit my post if still not working. – pawamoy Mar 29 '17 at 13:31

0 Answers0