property for class objects

Bengt Richter bokr at oz.net
Wed Nov 10 06:01:04 EST 2004


On Tue, 09 Nov 2004 23:08:44 -0500, Steve Menard <foo at bar.com> wrote:

>Jp Calderone wrote:
>> On Tue, 09 Nov 2004 21:54:50 -0500, Steve Menard <foo at bar.com> wrote:
>> 
>>>As par of JPype, I find that I have to brifge Java static members into 
>>>class attributes.
>>>
>>>I am using a metaclass to dynamically create a Python class for every 
>>>Java type encountered. Instance variables were handled by adding a 
>>>property(get, set) to the class's dictionary.
>>>
>>>Now static members are giving me a headache. I cannot use "property" for 
>>>them, because properties are for instances only.
>>>
>>>What I am currently doing is adding a __getattr__ and a __setattr__ 
>>>methods to the metaclass, which is called when a class attribute is 
>>>requested but not found in the class' dict.
>>>
>>>This works fine exact it does not walk the inheritance tree to find 
>>>static members defined in base classes. I am currently adding up all the 
>>>names in every class. This "works", however it is misleading when you do 
>>>a dir() of the class.
>>>
>>>Does anyone have an idea how to implement "classproperty" ?
>> 
>> 
>>   How about this?
>> 
>>     exarkun at boson:~$ python
>>     Python 2.3.4 (#2, Sep 24 2004, 08:39:09) 
>>     [GCC 3.3.4 (Debian 1:3.3.4-12)] on linux2
>>     Type "help", "copyright", "credits" or "license" for more information.
>>     >>> class x(type):
>>     ...     def get_y(self):
>>     ...             return 'y on', self
>>     ...     def set_y(self, value):
>>     ...             print 'y on', self, 'is now', value
>>     ...     y = property(get_y, set_y)
>>     ... 
>>     >>> class z(object):
>>     ...         __metaclass__ = x
>>     ... 
>>     >>> z.y
>>     ('y on', <class '__main__.z'>)
>>     >>> z.y = 'foo'
>>     y on <class '__main__.z'> is now foo
>>     >>> 
>> 
>>   If not, how is what you are looking for different?
>> 
>>   Jp
>
>I had thought about this solution. However, that would mean I would have 
>to define a Python metaclass (to hold the class properties) for each 
>Java class uses, as well as the Python class I already generate. I am 
>afraid this would en up being very heavy.
>
>I am not discarding this solution completely. It migth be that defining 
>those 2 (class and metaclass) isnt too heavy. Someone needs to clue me 
>in on this or I have to do some benchmarking myself.
>
>Hopefully, tehre is a cleaner way to solve this.
>
Sometimes a custom descriptor can get you there. You can pass stuff to its
constructor to hang on its self, which is accessible separately from the self
of an instance or the latter's class. So there is room for customizing various
descriptor instances using one class (not a metaclass). If you only need read
access, this is easy. If you want a r/w property you may have to go to a metaclass
solution unless you are willing to use  cvar.x = val or cvar[something] = var or
cvar.method(var) etc. -- i.e. return the descriptor self and have __setitem__ etc
as methods of the descriptor. You can hang something temporarily on self for use
in the subsequent method call, though I have the feeling there's some pitfall in
some uses of that. Anyway, here's a minimal descriptor (property is build on
the descriptor mechanisms, and you probably know all this, so I don't know why
I'm posting this ;-) IIRC, if you don't have a __set__ method, an attribute
assignment to an instance can shadow the descriptor, but not if you have __set__.
Of course, an attribute assignment to the class is no different than the original
class var assignment unless you have a descriptor/property in the metaclass to intercept it.

 >>> class Desc(object):
 ...     def __get__(self, inst, cls=None):
 ...         if inst is None: print 'accessed via class attribute'
 ...         else: accessed
 ...
 >>> class Desc(object):
 ...     def __get__(self, inst, cls=None):
 ...         if inst is None: print '%r accessed via class attribute' %cls
 ...         else:  print '%r accessed via instance attribute' %inst
 ...
 >>> class Foo(object):
 ...    cvar = Desc()
 ...
 >>> foo = Foo()
 >>> foo.cvar
 <__main__.Foo object at 0x009B61B0> accessed via instance attribute
 >>> Foo.cvar
 <class '__main__.Foo'> accessed via class attribute

Regards,
Bengt Richter



More information about the Python-list mailing list