[Tutor] design questions: pythonic approach to ostriches

Kent Johnson kent37 at tds.net
Sun Apr 24 14:04:57 CEST 2005


Brian van den Broek wrote:
> I do remain a bit surprised that there seems to be no way to implement 
> what I naively thought would be the obvious solution -- to remove an 
> inherited method from the instance's dictionary.

The thing is, the inherited method is never *in* the instance's dictionary. It's not in the 
instance's class's dictionary either. It only lives one place, in the base class's dictionary. So it 
is not possible to remove it from the derived class - it is not there.

  >>> class Base(object):
  ...   def p(self):
  ...     print 'Base.p()'
  ...

dir() shows attributes of Base and also of its base classes:
  >>> dir(Base)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', 
'__module__', '__new__', '__reduce__', '__reduce_ex__'
, '__repr__', '__setattr__', '__str__', '__weakref__', 'p']

Not all of these items are in Base.__dict__, some are inherited from object. For example 
__getattribute__ is an attribute of object:
  >>> print Base.__dict__
{'__dict__': <attribute '__dict__' of 'Base' objects>, 'p': <function p at 0x008D6D30>, 
'__module__': '__main__', '__weakref__': <attribute '__weakref
__' of 'Base' objects>, '__doc__': None}

If we derive from Base, we can see more of the same:
  >>> class Derived(Base):
  ...   def q(self):
  ...     print 'Derived.q()'
  ...
  >>> dir(Derived)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', 
'__module__', '__new__', '__reduce__', '__reduce_ex__'
, '__repr__', '__setattr__', '__str__', '__weakref__', 'p', 'q']

  >>> print Derived.__dict__
{'q': <function q at 0x008D6E30>, '__module__': '__main__', '__doc__': None}

There is no 'p' in Derived.__dict__.

So to 'remove' a method from Derived, you can't actually delete it from anywhere, you have to make 
it look like it is deleted.

One way to do this I have already suggested - make the Derived method raise AttributeError. This is 
the same exception you would get if it hadn't been defined and I think it will give a pretty 
convincing simulation.

Another way to do this would be to override Derived.__getattribute__() to watch for access to the 
derived method and raise AttributeError there.

Either one of these approaches should give a pretty good simulation of removing the attribute, 
though it still shows up if you dir(Derived). There doesn't seem to be a way to change that - I 
looked at the implementation of dir() (merge_class_dict() in object.c is the important part) and it 
doesn't have any hooks to customize it that I can see.

Whether you actually should do any of this is another question, I'll let my previous answer stand on 
that.

Kent



More information about the Tutor mailing list