Overriding a method at the instance level on a subclass of a builtin type
Arnaud Delobelle
arnodel at googlemail.com
Fri Dec 5 15:27:27 EST 2008
Arnaud Delobelle <arnodel at googlemail.com> writes:
> "Zac Burns" <zac256 at gmail.com> writes:
>
>> Ok. Feature request then - assignment of a special method name to an
>> instance raises an error.
>
> I haven't got the time to implement it, but I'm sure you can obtain the
> behaviour you want.
OK I've had half an hour to fill this afternoon so I tried to implement
it. I've restriced the ability to override special methods to
__getitem__ but this could be extended to any special method AFAICS. It
combines a metaclass and two descriptors (one for the metaclass and one
for the class), there may be a simpler way! It is proof-of-concept
code, I have not tried to make it behave sensibly when no __getitem__
method is defined (although that would be straighforward) and I have not
thought about how it would work with (multiple) inheritance (this may
require lots more thinking). Here it is, tested very succintly on
Python 2.5:
class ClassGetItem(object):
def __get__(self, obj, objtype=None):
return obj._getitem_
def __set__(self, obj, val):
obj._getitem_ = val
class GetItem(object):
def __get__(self, obj, objtype=None):
return obj._getitem_
def __set__(self, obj, val):
obj._getitem_ = val
class MetaOverrideSpecial(type):
def __new__(meta, name, bases, attrs):
if '__getitem__' in attrs:
attrs['_getitem_'] = attrs['__getitem__']
attrs['__getitem__'] = GetItem()
return type.__new__(meta, name, bases, attrs)
__getitem__ = ClassGetItem()
class OverrideSpecial(object):
__metaclass__ = MetaOverrideSpecial
Here is an example that shows it in action:
>>> class Foo(OverrideSpecial):
... def __getitem__(self, key): return 'Class getitem(%s)' % key
...
>>> foo=Foo()
>>> foo[3]
'Class getitem(3)'
Override the class's __getitem__ special method:
>>> Foo.__getitem__ = lambda self, key: 'Overriden class getitem(%s)' % key
>>> foo['bar']
'Overriden class getitem(bar)'
Override the instance's __getitem__ special method:
>>> foo.__getitem__ = lambda key: 'Instance getitem(%s)' % key
>>> foo['baz']
'Instance getitem(baz)'
What-a-way-to-waste-time'ly yours
--
Arnaud
More information about the Python-list
mailing list