synthetic properties

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Tue Sep 2 22:45:25 CEST 2008


rowland at river2sea.org a écrit :
> I'm trying to come up with solution for adding synthetic properties to
> python, similar to synthetic properties in Objective-C.

Please explain what Objective-C "synthetic properties" are - not 
everyone here has a strong Objective-C background...

> I'm playing around with doing this in a MetaClass.  I can dynamically
> create the attributes that will back the property, but I'm having
> trouble figuring out how to dynamically generate get/set methods to
> pass to the built-in property() function.

FWIW, the property type is just one possible application of the 
descriptor protocol. You can easily define your own custom descriptor 
classes - and you can even do this dynamically.

> Is it possible to define a lambda or a callable object that will act
> as a getter method (or setter, that takes a value argument) during
> MetaClass.__init__? 

Yes.

>  The hard part I'm guessing is getting the current
> instance passed into the getter.

Not really.

>  This is my first foray into
> MetaClasses and dynamic functions/methods so any pointers are greatly
> appreciated.
> 
> 
> class ObjectivePythonObject( type ) :
> 
>     def __new__( cls, name, bases, dct ) :
>         #print "Allocating memory for class", name
>         return type.__new__(cls, name, bases, dct )

This is what type.__new__ do, so you just don't need it.

>     def __init__( cls, name, bases, dct ) :
>         #print "Initializing class", name
>         for propertyInfo in cls.synthesized :
>             property = propertyInfo[ 0 ]
>             defaultValue = propertyInfo[ 1 ]
>             print property
>             setattr( cls, '_' + property, defaultValue )
>             # Create property with get/set methods...
> 
> class Person( object ) :
> 
>     __metaclass__ = ObjectivePythonObject
> 
> 
>     synthesized = [ ( 'name', 'BobC' ),
>                     ( 'age', '48' ) ]
> 
>     def __init__( self ) :
>         print self._name
>         print self._age
> 

<side-note>
May I suggest you read about Python's coding conventions ? Your code 
formatting is utterly unpythonic...
</side-note>

Ok, here's a working (and slightly more pythonic - at least wrt/ coding 
style) version of your code:

def _make_prop(attrname, default):
     def fget(self):
         return getattr(self, attrname, default)
     def fset(self, value):
         setattr(self, attrname, value)
     return property(fget=fget, fset=fset)

class ObjectivePythonType(type) :
     def __init__(cls, name, bases, dct):
         # we don't want to redefine properties already
         # defined in a base class
         synthesized = dct.get('synthesized', ())
         for propname, default in synthesized:
             attrname = "_%s" % propname
             setattr(cls, propname, _make_prop(attrname, default))


class ObjectivePythonObject(object):
     __metaclass__ = ObjectivePythonType

class Person(ObjectivePythonObject):
     synthesized = [
         ('name', 'BobC'),
         ('age', '48'),
         ]

     def __init__(self) :
         print self.name
         print self.age


Now... While all this is certainly usefull as a learning exercice on 
metaclasses etc, it's also an awfully overcomplexificated way to do 
something quite simple. Here's some code that do exactly the same thing:

class PythonPerson(object):
     name = "BobC"
     age = "48"

     def __init__(self):
         print self.name
         print self.age


HTH




More information about the Python-list mailing list