Re: dynamic, metaclasses and Virtual properties

Ernesto Revilla <[email protected]> Mon, 09 Aug 2004 12:29:14 +0200
Newsgroups gmane.comp.python.modeling
Message-ID <[email protected]>
Sebastien Bigaret escribió:

>        Hi Erny and all,
>
>On Wed, 30 Jun 2004, Ernesto Revilla <[email protected]> wrote:
>[original post can be found at:
> https://sf.net/mailarchive/forum.php?thread_id=5035017&forum_id=10674]
>
>  
>
>>I think that Python has a design error with properties, but it is easy to
>>correct this. 
>>    
>>
>[demonstration that properties aint behaving very good when it comes to
> inheritance]
>  
>
>>In Modeling, when inheriting from class created with properties (dynamic), it
>>does NOT the inherited methods. Is this reasonable?
>>    
>>
Sometimes I just forget the VERB. I mean 'apply' behind 'NOT' in the 
previous sentence. Properties bind directly to methods/functions (read 
method, write method, delete method). This is the result of descriptors 
implemented in python 2.2. There is still no syntactic sugar to use 
'virtualized' properties.

>You're right, this needs some attention, really.  Could you submit this
>as a bug report or as a patch proposal @sf.net please?
>  
>
I've sent a patch proposal.

>>Here I have attached a
>>little patch for dynamic.py. I made a local function mkProp, so that variable
>>binding is correct, otherwise  it does not work the way it should.
>>    
>>
>
>Can you be more explicit on this point?
>
>  
>
As you can see in the mkProp I create the methods like this:

getter=lambda s: getattr(s,'get'+name)()

Now, as lambda is evaluated, when it is called, it depends of what is 
the binding of the 'name' variable at this time. If I leave this outside 
of  a function and I have this is called several times, name changes, 
and at the end will have the last assigned value, so all getters created 
with the statement will refere effectively to the same attribute, as all 
getters will evaluate 'name' to the same value. Say you have 3 
attributes: name, surname and age, and call the above statement, 3 times 
in the same order for each attribute, you'll get 3 functions, but all 
the three functions will call getAge, because 'name' will bind to 'age'. 
To force the binding, I built the mkProp function and put the 
statement   ( getter=lambda s: getattr(s,'get'+name)() ) into the 
function body. This forces to copy the binding to a local variable, the 
function parameter. So each time I call mkProp, name will be bound to 
another value, and will be retained as the lambda expression refers to it.

I think the same thing can be accomplished in another way, e.g. as you 
do by creating methods from source code. I still haven't tried using 
this approach.

>>Just a
>>remark about the setter. As in the original code, a virtual setter is created
>>only if the attribute is settable in the base class. In this case, we have two
>>alternatives: 1. do not create a setter, as the original code, 2. create
>>always a virtual setter and the setter in the base class raises a
>>ReadOnlyAttributeException. (This is was I have done in a experimental
>>framework.)
>>    
>>
>
>For the moment being we're not handling any 'readOnly' properties on
>attributes --and the one in entity is still ignored for now, so I can't
>really see whazt your point is, I suspect I'm misunderstanding something
>here.
>
>  
>
I used that for a mini testing framework I wrote, where i defined 
read-only attributes. So, please ignore it at this time.

>  Oh, and BTW sorry for taking such a long time to answer :/
>  
>
No problem at all. I just wanted to make the point clear of using 
properties.

Regards, Erny