From: kedra marbun on
On Jul 7, 2:46 am, Bruno Desthuilliers
<bdesth.quelquech...(a)free.quelquepart.fr> wrote:
> Gregory Ewing a écrit :
>
> > Bruno Desthuilliers wrote:
> >> kedra marbun a écrit :
>
> >>> if we limit our discussion to py:
> >>> why __{get|set|delete}__ don't receive the 'name' & 'class' from
> >>> __{getattribute|{set|del}attr}__
> >>> 'name' is the name that is searched
>
> >> While it would have been technically possible, I fail to imagine any use
> >> case for this.
>
> > I think he wants to have generic descriptors that are
> > shared between multiple attributes, but have them do
> > different things based on the attribute name.
>
> I already understood this, but thanks !-)
>
> What I dont understand is what problem it could solve that couldn't be
> solved more simply using the either _getattr__ hook or hand-coded
> delegation, since such a descriptor would be so tightly coupled to the
> host class that it just doesn't make sense writing a descriptor for this.

yeah, i finally can agree descriptor isn't supposed to be used as
delegation in general, it should be the job of __getattr__

however i still think passing name would open up some other
possibilities of use (not necessarily on the basis of sharing
descriptor), surely some of them (all of it?) are bad. sure as hell,
my example is an example of bad use. for now, i conclude that passing
name is too risky, it easily allows bad practices particularly against
the law of Demeter

thanks Bruno

btw, is there a common approach to let the interface of a class that
uses __getattr__, to include names that are delegated?

class A:
def do_this(self): ...

class B:
a = A()
def do_that(self): ...

def __getattr__(self, name):
try:
return types.MethodType(getattr(self.a, name), self)
except AttributeError:
raise AttributeError

how to make 'dir(B)' includes 'do_this', do i have to use __dir__? and
if i use __dir__, somewhat 'help(B)' doesn't work as usual, i haven't
check pydoc.py ;)
From: kedra marbun on
On Jul 6, 12:11 pm, Steven D'Aprano <steve-REMOVE-
T...(a)cybersource.com.au> wrote:
> On Mon, 05 Jul 2010 21:12:47 -0700, kedra marbun wrote:
> > On Jul 5, 7:49 am, Gregory Ewing <greg.ew...(a)canterbury.ac.nz> wrote:
> >> kedra marbun wrote:
> >> > now, i'm asking another favor, what about the 2nd point in my 1st
> >> > post?
>
> >> Your original post has dropped off my newsscope, so you'll have to
> >> remind me what the 2nd point was.
>
> >> --
> >> Greg
>
> > it's like 'name', it's about info that i think should be passed to
> > descriptor's __{get|set|delete}__. i wonder what are the reasons for not
> > passing the class on which the descriptor is attached to, what pattern
> > is encouraged by this?
>
> Perhaps I'm missing the context, but since the descriptor is passed the
> instance, you can easily get the class with type(self) or self.__class__.
> There's no need to pass the class as a separate argument.
>
> --
> Steven

no, the class that i meant is the one that actually has the descriptor
in its __dict__, not instance.__class__

the class obj that you said unecessary-as-arg is what __get__ receives
as the 3rd arg

class Desc:
def __get__(*args): print(args)

class a:
v0 = Desc()

class b(a): pass

b().v0 #(desc, b(), b)
From: Bruno Desthuilliers on
kedra marbun a �crit :
> On Jul 7, 2:46 am, Bruno Desthuilliers
> <bdesth.quelquech...(a)free.quelquepart.fr> wrote:
>> Gregory Ewing a �crit :
>>
>>> Bruno Desthuilliers wrote:
>>>> kedra marbun a �crit :
>>>>> if we limit our discussion to py:
>>>>> why __{get|set|delete}__ don't receive the 'name' & 'class' from
>>>>> __{getattribute|{set|del}attr}__
>>>>> 'name' is the name that is searched
>>>> While it would have been technically possible, I fail to imagine any use
>>>> case for this.
>>> I think he wants to have generic descriptors that are
>>> shared between multiple attributes, but have them do
>>> different things based on the attribute name.
>> I already understood this, but thanks !-)
>>
>> What I dont understand is what problem it could solve that couldn't be
>> solved more simply using the either _getattr__ hook or hand-coded
>> delegation, since such a descriptor would be so tightly coupled to the
>> host class that it just doesn't make sense writing a descriptor for this.
>
> yeah, i finally can agree descriptor isn't supposed to be used as
> delegation in general, it should be the job of __getattr__
>
> however i still think passing name would open up some other
> possibilities of use

Nothing prevents you to pass a "name" to the descriptor instance when
instanciating it, ie:

class Desc(object):
def __init__(self, name):
self.name = name
def __get__(self, inst, cls):
# ...
def __set__(self, inst, value):
# ...


class Foo(object):
bar = Desc("bar")
baaz = Desc("baaz")

Ok, this is not necessarily what you were looking for, but it's IMHO
less brittle than relying on which attribute name was looked up (which
is something the descriptor shouldn't have to care about).

>
> btw, is there a common approach to let the interface of a class that
> uses __getattr__, to include names that are delegated?

In Python 2.x, not that I know (but it may have passed under my radar).
If what you want it to automate delegation of a set of methods without
too much manual coding, you can use a custom metaclass that will add the
relevant methods to the class, based on (ie) a list (or mapping) of
methods names. But that might be a bit overkill.

> class A:
> def do_this(self): ...
>
> class B:
> a = A()

I don't see the point of using delegation on a class attribute. That's
typically what inheritance is for.

> def do_that(self): ...
>
> def __getattr__(self, name):
> try:
> return types.MethodType(getattr(self.a, name), self)

Err... Did you try the simple way ?
return getattr(self.a, name)

From: Gregory Ewing on
kedra marbun wrote:
> i wonder what are the reasons for
> not passing the class on which the descriptor is attached to, what
> pattern is encouraged by this?

The same answer applies. It's assumed that you will be
writing a custom piece of code for each attribute of
each class, and giving each one its own descriptor.

By the time you get to the get or set method of a
descriptor, you've already dispatched on both the
class and attribute name. There is not usually any
point in funnelling things back into a single function
and then dispatching on the class or name again.
Passing the class or name would just add overhead that
was unnecessary in the majority of use cases.

--
Greg
From: kedra marbun on
On Jul 8, 4:02 pm, Bruno Desthuilliers <bruno.
42.desthuilli...(a)websiteburo.invalid> wrote:
> kedra marbun a écrit :
>
>
>
> > On Jul 7, 2:46 am, Bruno Desthuilliers
> > <bdesth.quelquech...(a)free.quelquepart.fr> wrote:
> >> Gregory Ewing a écrit :
>
> >>> Bruno Desthuilliers wrote:
> >>>> kedra marbun a écrit :
> >>>>> if we limit our discussion to py:
> >>>>> why __{get|set|delete}__ don't receive the 'name' & 'class' from
> >>>>> __{getattribute|{set|del}attr}__
> >>>>> 'name' is the name that is searched
> >>>> While it would have been technically possible, I fail to imagine any use
> >>>> case for this.
> >>> I think he wants to have generic descriptors that are
> >>> shared between multiple attributes, but have them do
> >>> different things based on the attribute name.
> >> I already understood this, but thanks !-)
>
> >> What I dont understand is what problem it could solve that couldn't be
> >> solved more simply using the either _getattr__ hook or hand-coded
> >> delegation, since such a descriptor would be so tightly coupled to the
> >> host class that it just doesn't make sense writing a descriptor for this.
>
> > yeah, i finally can agree descriptor isn't supposed to be used as
> > delegation in general, it should be the job of __getattr__
>
> > however i still think passing name would open up some other
> > possibilities of use
>
> Nothing prevents you to pass a "name" to the descriptor instance when
> instanciating it, ie:
>
> class Desc(object):
>      def __init__(self, name):
>          self.name = name
>     def __get__(self, inst, cls):
>         # ...
>     def __set__(self, inst, value):
>         # ...
>
> class Foo(object):
>      bar = Desc("bar")
>      baaz = Desc("baaz")
>
> Ok, this is not necessarily what you were looking for, but it's IMHO
> less brittle than relying on which attribute name was looked up (which
> is something the descriptor shouldn't have to care about).
>
>
>
> > btw, is there a common approach to let the interface of a class that
> > uses __getattr__, to include names that are delegated?
>
> In Python 2.x, not that I know (but it may have passed under my radar).
> If what you want it to automate delegation of a set of methods without
> too much manual coding, you can use a custom metaclass that will add the
> relevant methods to the class, based on (ie) a list (or mapping) of
> methods names. But that might be a bit overkill.
>
> > class A:
> >    def do_this(self): ...
>
> > class B:
> >    a = A()
>
> I don't see the point of using delegation on a class attribute. That's
> typically what inheritance is for.

ah, our friend mixin, it's just a sample though
>
> >    def do_that(self): ...
>
> >    def __getattr__(self, name):
> >            try:
> >                    return types.MethodType(getattr(self.a, name), self)
>
> Err... Did you try the simple way ?
>                          return getattr(self.a, name)

argh, that should be
class A:
def do_this(self, ins): ...