[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