Dynamically creating class properties

Michael Spencer mahs at telcopartners.com
Thu Oct 4 19:35:35 EDT 2007


Karlo Lozovina wrote:

> 
> Any idea how to do that with metaclasses and arbitrary long list of 
> attributes? I just started working with them, and it's driving me nuts :).
> 
> Thanks for the help,
> best regards.
> 
Try implementing a property factory function before worrying about the 
metaclass.  Assuming you need a standard getter and setter, then the following 
(untested) example may be useful.  If you need custom get/set behavior then you 
would rewrite the factory to accept passed-in functions.

  >>> def make_data_property(cls, prop_name):
  ...
  ...     # create default methods that get and set a 'private' instance
  ...     # attribute
  ...     def _set(self, value):
  ...         setattr(self, "_%s" % prop_name, value)
  ...     def _get(self):
  ...         # None is default.  Alternatively handle AttributeError
  ...         return getattr(self, "_%s" % prop_name, None)
  ...
  ...     setattr(cls, prop_name, property(_get, _set))
  ...
  ...     # optionally, fix the internal names of the _get and _set for better
  ...     # introspection
  ...     _set.func_name = setname = "set%s" % prop_name
  ...     _get.func_name = getname = "get%s" % prop_name
  ...
  ...     # optionally, make _get and _set members of the class, if you want to
  ...     # call them directly (but then, why have the property?)
  ...     setattr(cls, setname, _set)
  ...     setattr(cls, getname, _get)
  ...
  >>> class A(object):
  ...     pass
  ...
  >>> a=A()
  >>> a.item1
  Traceback (most recent call last):
    File "<input>", line 1, in <module>
  AttributeError: 'A' object has no attribute 'item1'
  >>> make_data_property(A,"item1")
  >>> a.item1
  >>> a.item1 = 42
  >>> a.item1
  42
  >>> make_data_property(A,"item2")
  >>> a.item2
  >>> a.item2 = 43
  >>>
  >>> a.item2
  43
  >>>

If you can get this piece working, then multiple attributes should be easy. 
Then, if you like, you can call your property factory from the metaclass 
__init__ method.

HTH
Michael




More information about the Python-list mailing list