property using a classmethod

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Fri Jul 10 12:38:49 CEST 2009

Bruno Desthuilliers a écrit :
> You could write your own custom descriptor. Or just use an additional 
> level of indirection, ie:
>    myProperty = property(lambda self: self.myClassMethod())

Sorry, looks like I didn't read carefully enough. The above code won't 
work if you intend to lookup the property directly on the class object, 
ie "MyClass.myProperty". If that was your intention, you'll need a 
custom descriptor. The following code should do the job, or at least get 
you started:

# python 2.5.x

# the custom (non binding) descriptor
class ClsProperty(object):
     def __init__(self, fget):
         if not isinstance(fget, (classmethod, staticmethod)):
             # XXX better error message
             raise ValueError(
               "fget must be a classmethod or staticmethod"
         self.fget = fget

     def __get__(self, obj, cls=None):
         if cls is None:
             assert obj is not None
             cls = type(obj)
         return self.fget.__get__(obj, cls)()

# helper -> a simple decorator
def classproperty(func):
     if not isinstance(func, (classmethod, staticmethod)):
         func = classmethod(func)
     return ClsProperty(func)

# example use
class Foo(object):

     # the hard way
     def bar(cls):
         return "" % cls.__name__

     quux = ClsProperty(bar)

     # the simple way
     def baaz(cls):
         return "%s.baaz" % cls

Given your example, this should be enough. If you need a binding 
descriptor (one with a setter), you'll have to implement the __set__ 
method (and possibly __del__). Google for "python descriptor" to find 
more doc about the descriptor protocol.


More information about the Python-list mailing list