I coded a metaclass
that defines in run time properties of the class that use it. It just gets these attributes from the REQUIRED_KEYS attribute to then declare a property
, for example:
class Base(object):
REQUIRED_KEYS = ()
class __metaclass__(type):
def __init__(cls, name, bases, nmspc):
type.__init__(cls, name, bases, nmspc)
for attr in cls.REQUIRED_KEYS:
setattr(cls, attr, property(lambda self: self._dict.get(attr, None)))
def __init__(self, **kwargs):
self._dict = dict(**kwargs)
class Config(Base):
REQUIRED_KEYS = ('foo', 'bar')
If one key is not given the attribute defined in run time returns a None
value. I would expected a right behaviour for the following execution, returning 1
and None
:
config = Config(**{'foo': 1})
config.foo
config.bar
But it returns None for the foo
attribute where the right value expected will be 1
.
If I modify the lambda
used by the property
function by one closure as the following snippet shows, it works fine.
class __metaclass__(type):
def __init__(cls, name, bases, nmspc):
def get(attr):
def _get(self):
return self._dict.get(attr, None)
return _get
type.__init__(cls, name, bases, nmspc)
for attr in cls.REQUIRED_KEYS:
setattr(cls, attr, property(get(attr)))
Following the execution of the first snippet, I realised that the lambda function is always called with the last attr
value. It means that when we are trying to access to the foo
attribute the lambda uses the bar
value.
does anybody know what is going on here ?