Class property

Laszlo Zsolt Nagy gandalf at designaproduct.biz
Thu Oct 6 10:09:22 EDT 2005


Peter Otten wrote:

>Laszlo Zsolt Nagy wrote:
>
>  
>
>>I was trying for a while, but I could not implement a 'classproperty'
>>function. Is it possible at all?
>>    
>>
>
>You could define a "normal" property in the metaclass:
>  
>
The only way I could do this is:

class MyXMetaClass(type):
    _x = 0
    def get_x(cls):
        print "Getting x"
        return cls._x
    def set_x(cls,value):
        cls._x = value
        print "Set %s.x to %s" % (cls.__name__,value)
    x = property(get_x,set_x)

class A(object):
    __metaclass__ = MyXMetaClass
   
print A.x
A.x = 8


Results in:

Getting x
0
Set A.x to 8

But of course this is bad because the class attribute is not stored in 
the class. I feel it should be.
Suppose we want to create a class property, and a class attribute; and 
we would like the property get/set methods to use the values of the 
class attributes.
A real example would be a class that keeps track of its direct and 
subclassed instances:

class A(object):
    cnt = 0
    a_cnt = 0
    def __init__(self):
        A.cnt += 1
        if self.__class__ is A:
            A.a_cnt += 1
           
class B(A):
    pass
   
print A.cnt,A.a_cnt # 0,0
b = B()
print A.cnt,A.a_cnt # 1,0
a = A()
print A.cnt,A.a_cnt # 2,1

But then, I may want to create read-only class property that returns the 
cnt/a_cnt ratio.
This now cannot be implemented with a metaclass, because the metaclass 
cannot operate on the class attributes:

class A(object):
    cnt = 0
    a_cnt = 0
    ratio = a_class_property_that_returns_the_cnt_per_a_cnt_ratio() # ????
    def __init__(self):
        A.cnt += 1
        if self.__class__ is A:
            A.a_cnt += 1

Any ideas?

   Les






More information about the Python-list mailing list