On and off, I've been looking for an elegant way to handle properties using 
decorators.

It hasn't really worked, because decorators are inherently single function, 
and properties span multiple functions.

However, it occurred to me that Python already contains a construct for 
grouping multiple related functions together: classes.

And that thought led me to this decorator:

   def def_property(cls_func):
       cls = cls_func()
       try:
           fget = cls.get.im_func
       except AttributeError:
           fget = None
       try:
           fset = cls.set.im_func
       except AttributeError:
           fset = None
       try:
           fdel = cls.delete.im_func
       except AttributeError:
           fdel = None
       return property(fget, fset, fdel, cls.__doc__)

Obviously, this decorator can only be used by decorating a function that 
returns the class of interest:

   class Demo(object):
      @def_property
      def test():
          class prop:
              """This is a test property"""
              def get(self):
                  print "Getting attribute on instance"
              def set(self, value):
                  print "Setting attribute on instance"
              def delete(self):
                  print "Deleting attribute on instance"
          return prop

Which gives the following behaviour:

Py> Demo.test
<property object at 0x00B9CC38>
Py> Demo().test
Getting attribute on instance
Py> Demo().test = 1
Setting attribute on instance
Py> del Demo().test
Deleting attribute on instance
Py> help(Demo.test)
Help on property:

     This is a test property

     <get> = get(self)

     <set> = set(self, value)

     <delete> = delete(self)

If we had class decorators, though, the decorator could be modified to skip 
the function invocation:

   def def_property(cls):
       try:
           fget = cls.get.im_func
       except AttributeError:
           fget = None
       try:
           fset = cls.set.im_func
       except AttributeError:
           fset = None
       try:
           fdel = cls.delete.im_func
       except AttributeError:
           fdel = None
       return property(fget, fset, fdel, cls.__doc__)

And the usage would be much more direct:

   class Demo(object):
      @def_property
      class test:
          """This is a test property"""
          def get(self):
              print "Getting attribute on instance"
          def set(self, value):
              print "Setting attribute on instance"
          def delete(self):
              print "Deleting attribute on instance"


Comments? Screams of horror?

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.blogspot.com
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to