Is there a way to 'mask out' inherited methods?

Ralf Juengling juenglin at informatik.uni-freiburg.de
Fri May 3 15:00:06 EDT 2002


Alex Martelli <aleax at aleax.it> writes:

> Ralf Juengling wrote:
>         ...
> > I'm fiddling around with some new 2.2.-features. I want to
> > inherit from a builtin-type but want to use only a subset
> > of its functionality:
> > 
> > class Vector(list):
>         ...
> > I.e. Vector should keep or inherit methods meaningful to vectors
> > (e.g. '__str__', '__getitem__', '__cmp__' and so on), and should
> > somehow undefine or mask out any methods not meaningful to it
> > ('append', 'reverse', ..).
> > 
> > Any idea how to achieve that easily?
> 
> "Easily" within the constraints you stated, only one way: add a
> __getattribute__ method that selects only the attributes (note that
> methods are also attributes) you want to expose, e.g.:
> 
> class Vector(list):
>     mymethods = '__str__', '__getitem__', '__cmp__'
>     def __getattribute__(self, name):
>         if name in self.mymethods:
>             return object.__getattribute__(self, name)
>         else: raise AttributeError, name
> 
> Forget *SPEED*, of course -- when you define __getattribute__
> Python calls it for EVERY attribute request, so your code will just
> crawl.  For speed, your choice is: either drop the constraint that
> Vector must subclass list, and delegate instead; or, if the constraint
> MUST be kept, override all methods you want to 'mask out' and
> have each of them raise AttributeError (not quite the same thing,
> of course -- getattr would still 'see' them, for example).  A custom
> metaclass might help (not trivial).
> 

Thanks for your answers (to all of you).

I still have problems to get the right picture about
instance attributes. At first I thought, anything is 
dynamic and 'bound methods' and 'data attributes' we're
treated similar in that you can add and remove them 
at runtime if you like. Then one could sth like this:

class A:

    def __init__(self):
        pass
   
    def mA(self):
        print "Here I am."
    
class B(A):

    def __init__(self):
        A.__init__self)
        del self.mA

    def mB(self):
        print "Me too."


This doesn't work; I get:
 
>>> b = B()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "vector1.py", line 47, in __init__
    del self.mA
AttributeError: B instance has no attribute 'mA'


Okay. Just to try, I changed A to a new-style class
(class A(object): ). In this case I get:

>>> b = B()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "vector1.py", line 47, in __init__
    del self.mA
AttributeError: 'B' object attribute 'mA' is read-only

So, what's that?

I've already heard that the 'attribute resolving-' or 
'attribute access-'methodology changed in 2.2, i.e.
there are now special 'descriptor objects' for that 
purpose. However, I don't understand what's going on.

What happens -- in terms of descriptors -- when the 
following expressions are evaluated? (Imagine the del
statement in B.__init__ is absent and):

b = B()

1. b.mA()
2. b.mB()

3. b.mA = 'eat that'
4. b.mB = 'or that'

5. del b.mA
6. del b.mB


Thanks,
Ralf



More information about the Python-list mailing list