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

Alex Martelli aleax at aleax.it
Sat May 4 01:57:22 EDT 2002


Steve Holden wrote:
        ...
>> >>> 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?
>>
> Well I'm only going to put a toe in this water, as this stuff is pretty
> new. Alex can set you straight is necessary. New-style classes appear
> (from this error message :-) to bind method names much more rigidly than
> classis classes. They are therefore not amenable to the same naughty games
> you could classically play with your classes and objects.

It's just a clearer and more precise error message -- you couldn't do
this in classic classes either:

[alex at arthur alex]$ /usr/bin/python
Python 2.0 (#1, Apr 11 2001, 19:18:08)
[GCC 2.96 20000731 (Linux-Mandrake 8.0 2.96-0.48mdk)] on linux-i386
Type "copyright", "credits" or "license" for more information.
>>> class A:
...   def mA(self): print 'mA'
...
>>> class B(A):
...   def __init__(self):
...     del self.mA
...
>>> b=B()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in __init__
AttributeError: delete non-existing instance attribute
>>>

"non-existing" was maybe a bit too strong; "read-only" may be a better
description.  But the gist is the same!

Despite the threatening rumblings heard throughout the latter half of the
year 2001, new-style classes actually came out with an amazing level
of compatibility to classic ones, including support for most of the dirty
tricks you could play.  When you notice a difference, it's generally because
the role of metaclass vs class vs instance has been made more regular
and logical.

For example: when I write x(), where should Python look for a __call__
special method to call?  Used to be: if x is a class, then only the 
metaclass was considered; but if x was an instance, then first the
instance was examined, then, failing that, the class.  (And similarly
for other special methods).  Now, it's become totally regular: when
looking for a special method, x itself is NOT examined, but its class
is (if x is a class, x's class is the metaclass, of course).  So, x() is
never affected (in the new object model) by whether x itself has a
__class__ attribute or not.  [and similarly for other specials].

But none of this affects the OP's problems.


>> 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.
>>
> Me neither. Where is Alex when you need him? <wink>

Heroically here writing when I should go get coffee instead
(not 8AM yet here...).

Descriptors regularize things but don't affect the "way to
mask out inherited methods" -- __getattribute__ was added
so you can now do that (slowly:-) where earlier you could not,
and you could try your hand at writing a custom metaclass for
such masking purposes (not trivial), but by far the best approach
remains as it always was to eschew inheritance when it does
not meet your needs in favour of automatic (possibly selective)
delegation/aggregation/containment.


Alex




More information about the Python-list mailing list