derived classes and __getattr__

Alexandru Mosoi brtzsnr at gmail.com
Fri Sep 5 08:49:48 EDT 2008


On Sep 5, 1:13 pm, Peter Otten <__pete... at web.de> wrote:
> Alexandru  Mosoi wrote:
> > On Sep 5, 11:47 am, Peter Otten <__pete... at web.de> wrote:
> >> Alexandru Moșoi wrote:
> >> > i'm facing the following problem:
>
> >> > class Base(object):
> >> > def __getattr__(self, attr): return lambda x: attr + '_' + x
>
> >> > def dec(callable):
> >> > return lambda *args: 'dec_' + callable(*args)
>
> >> > class Derived(Base):
> >> > what_so_ever = dec(Base.what_so_ever) # wrong, base doesn't have
> >> > what_so_ever
> >> > mumu = dec(Base.mumu)                          # wrong, base
> >> > doesn't have mumu
>
> >> > any idea how to do this?
>
> >> __getattr__() is defined in the class to create instance attributes on
> >> the fly. If you want class attributes you have to put the __getattr__()
> >> method into the class of the class, or "metaclass":
>
> >> class Base(object):
> >> class __metaclass__(type):
> >> def __getattr__(self, attr):
> >> return lambda self, x: attr + '_' + x
>
> >> def dec(callable):
> >> return lambda *args: 'dec_' + callable(*args)
>
> >> class Derived(Base):
> >> what_so_ever = dec(Base.what_so_ever)
>
> >> d = Derived()
> >> print d.what_so_ever("42")
>
> >> I don't see how you can turn this into something useful...
>
> >> Peter
>
> > 10x. it works. however I have another small problem. now,
> > d.third('blah') doesn't work because instance d doesn't have 'third'
> > attribute. I was expecting derived class to inherit the metaclass as
> > well, but it didn't.
>
> That has nothing to do with inheritance:
>
> >>> type(Derived)
>
> <class 'classattr.__metaclass__'>
>
> If Python doesn't find an attribute in the instance it looks it up in the
> class but not in the metaclass:
>
> >>> Base.third
>
> <function <lambda> at 0x2b5f8028aa28>>>> Base().third
>
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: 'Base' object has no attribute 'third'
>
> I think you should go back to the drawing board now and look for a simpler
> approach to solve your actual problem...
>
> Peter


i somehow fixed the problem using:

  def __getattr__(self, attr):
        return
functools.partial(Base.__metaclass__.__getattr__(self.__class__,
attr), self)

however this looks ugly enough to look for another solution. i still
have one more question: why do I have to bind self? (without which
functions fail expecting an instance)



More information about the Python-list mailing list