delegation pattern via descriptor

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Tue Jul 6 04:05:47 EDT 2010


kedra marbun a écrit :
> On Jul 5, 3:42 pm, Bruno Desthuilliers <bruno.
> 42.desthuilli... at websiteburo.invalid> wrote:
>> kedra marbun a écrit :
>>
>>
>>
>>> i'm confused which part that doesn't make sense?
>>> this is my 2nd attempt to py, the 1st was on april this year, it was
>>> just a month, i'm afraid i haven't got the fundamentals right yet. so
>>> i'm gonna lay out how i got to this conclusion, CMIIW
>>> **explanation of feeling (0) on my 1st post**
>>> to me, descriptor is a particular kind of delegation, it takes the job
>>> of coding the delegation by having a contract with programmers that
>>> the tree meta operations (get, set, del) on attr are delegated to the
>>> obj that is bound to the attr
>>> are we agree that descriptor is a kind of delegation?
>>> the mechanism that makes descriptor works is in __getattribute__,
>>> __setattr__, __delattr__ of 'object' & 'type'
>>> now, if i want a single descriptor obj to be delegated to multiple
>>> tasks, i can't do it since __get__ doesn't get info that can be used
>>> to determine which task to do
>>> i must have diff descriptor obj for each task
>>> class Helper:
>>>    def __init__(self, name):
>>>            self.name = name
>>>    def __get__(self, ins, cls):
>>>            if self.name == 'task0': ...
>>>            elif self.name == 'task1': ...
>>>            else: ...
>> Replacing such "big switch" code with polymorphic dispatch is one of the
>>   goals (and feature) of OO. This should be:
>>
>> class Task0(object):
>>      def __get__(self, obj, cls):
>>          # code here
>>
>> class Task1(object):
>>      def __get__(self, obj, cls):
>>          # code here
>>
>> class A(object):
>>      task0 = Task0()
>>      task1 = Task1()
>>
>> If you have common code to share between TaskO and Task1 then factor it
>> out into a base class.
>>
>>> if __get__ receives the name, then i could do
>>> class Helper:
>>>    def __get__(self, ins, cls, name):
>>>            ...
>>> class a:
>>>    task0 = task1 = Helper()
>> Yuck.
> 
> what's so 'Yuck' about it? ;)

It's an implicit, obfuscated and overcomplicated way to do a very simple 
thing. To be true, I just don't see the point of this pattern - Python 
has better solutions for delegation (cf the __getattr__ method), and 
that's not what descriptors are for.


> i guess i need a strong stmt: is descriptor a kind of delegation? or
> is it not?

The descriptor protocol is the primary support for computed attributes. 
As such it can be used as a support for delegation, but it's not "a kind 
of delegation" by itself.

> * if it is a kind of delegation, then the code that you labeled as
> 'Yuck' is just a result of applying delegation
> what's wrong with delegating multiple tasks to a single obj?

Nothing wrong with delegating multiple tasks to a single object - but 
not that way. If you want to use descriptors to specify which tasks 
should be delegated, you'd be better doing it more explicitely - that 
is, only use the descriptor as a gateway, and use one descriptor per task.

Else just use __getattr__ !-)

Sorry, I don't have much time to elaborate on this now.

> that code is similar to this
> 
> class Helper:
> 	def do_this(self, ins): ...
> 	def do_that(self, ins): ...
> 
> class a:
> 	delegate = Helper()
> 	def task0(self): self.delegate.do_that(self)
> 	def task1(self): self.delegate.do_this(self)
> 

It's not similar. This second example is explicit, and doesn't couple 
Helper to a.


My 2 cents.



More information about the Python-list mailing list